指令的基础认识
angularjs指令:解决html标签复用
angularjs指令可以指定一个标签,让后用template去替换指定标签的内容
下面是一个小案例,对指令结构的基本解释
html结构:
<div ng-app="s9.app">
<!--指令的 标签名用法,指令名用作了标签名-->
<s9-header></s9-header>
<!--指令的 属性名的方法,指令名用作了属性名-->
<div s9-header></div>
</div>
js代码:
var app = angular.module("s9.app",[]);
app.directive("s9Header",function(){
var directiveObj = {
template:'<div class="page-header">'
+ '<h1>流行框架阶段 <small>AngularJs指令</small></h1>'
+ '</div>'
};
return directiveObj;
});
解析:
app.directive()用来定义一个指令,
第一个参数:指令名字,同时也会被: 用作html上的属性名或是标签名
所以:必须使用驼峰语法,到页面上就会自动转为横线连接(s9-header)
第二个参数:指令的工厂函数
返回一个对象(directiveObj),这个对象描述了我们的指令如何被angularjs解析
directiveObj:
用于描述这个指令的对象,这个对象中的各种字段,都是angularjs规定的
template:
指令的模板,当使用这个指令时,模板的内容替换对应标签的标签体
(使用的结果:用标签或者属性名方法,放到html上,指定某个标签)
replace
replace设置为true:完全替换了自定义标签,自定义标签就不存在了
标签名用法、属性名用法的自定义标签都不存在了
**如果用的是属性名方法自定义标签,那么指令名字的属性会保留在指令指定的标签中(s9-header)使用replace有一个小问题!!!
template模板中的标签不能是并行的,也就是必须要有一个根元素
原因:
replace为true时,会把自定义标签替换,指令的作用域就作用在模板指定的标签上;
一个指令(directive)要绑定在两个并行的标签上,指令就不知道到底要绑定到哪个标签上,就会报错
html结构:
<div ng-app="s9.app">
<!--指令的 标签名用法,指令名用作了标签名-->
<s9-header></s9-header>
<!--指令的 属性名的方法,指令名用作了属性名-->
<!--此时查看html代码,会发现s9-header这个属性会保留在指令指定的标签中-->
<div s9-header></div>
</div>
js代码:
var app = angular.module("s9.app",[]);
app.directive("s9Header",function(){
var directiveObj = {
template:'<div class="page-header">'
+ '<h1>流行框架阶段 <small>AngularJs指令</small></h1>'
+ '</div>',
// replace用法
replace: true
};
return directiveObj;
});
transclude
允许在指令的template里面指定一个标签(用ng-transclude指令指定),然后把外部的内容嵌入到这个标签中。外部的内容:宿主标签原来的标签体内容
如果自定义标签中有字符串,则会被覆盖
html结构
<div ng-app="s9.app">
<s9-panel>我是宿主标签中的内容</s9-panel>
</div>
js代码
var app = angular.module("s9.app",[]);
app.directive("s9Panel",function(){
var templateSrt =
'<div>'
+ '<div ng-transclude>' //加上ng-transclude
+ '</div>'
+ '</div>';
var directiveObj = {
template: templateSrt,
transclude: true
};
return directiveObj;
});
scope
scope字段未设置或设置为false:
使用指令所指定标签的外部的作用域(没有自己作用域),该指令继承了
父作用域的一切属性和方法,所以在中的模板中我们可以使用这些属性和方法
在指令中修改数据时,会反应到父作用域的模型中
因为他两就是同一个作用域scope字段或设置为true:
创建了一个新作用域,这个作用域继承了我们的父作用域,
此时在input中输入,指令的msg发生了变化,指令外的 msg 没有发生 变化
可以理解为:新创建的作用域是一个新作用域,只不过在初始化的时候,用了父作用域的属性和方法去填充这个新作用域,它和作用域不是同一个作用域
html结构
<div ng-controller="MainController">
<div>控制器:{{msg}}</div>
<!--继承的是MainController作用域-->
<s9-panel></s9-panel>
</div>
js代码:
var app = angular.module("s9.app",[]);
app.run(function($rootScope){
$rootScope.msg = "hello run";
});
app.controller("MainController",function($scope){
$scope.msg = "hello controller";
})
app.directive("s9Panel",function(){
var templateSrt = "<div><input type='text' ng-model='msg'></div>";
var directiveObj = {
template: templateSrt,
scope: false
};
return directiveObj;
})
scope设置为自定义对象时
scope设置为自定义对象,就代表使用的是孤立作用域(隔离作用域)
html结构:
<div ng-app="s9.app">
<div ng-controller="MyController">
<div>{{msg}}</div>
<div my-music my-word="happy" my-col="msg+'...'" my-ipt='msg'></div>
</div>
</div>
js代码:
var app = angular.module("s9.app",[]);
app.controller("MyController",function($scope){
$scope.msg = "hello";
})
app.directive("myMusic",function(){
var templateStr = "<span>{{myWord}}</span>";
var obj = {
template: templateStr,
scope: {
myWord:"@",
// 如果属性值中有插值语法,先运算插值语法的值
// 再把字符串传递过来
myCol:"<",
// 和外部作用域指定的字段的数据 做了一个双向的数据绑定
myIpt:"="
},
// 因为是孤立作用域,所以访问不到父元素作用域中的msg
// 结果就是undefined
controller:function ($scope) {
console.log($scope.msg);
}
};
return obj;
})
代码解析:
- ‘@’ 作用(传纯字符串):
可以将宿主标签上的属性值绑定到template指定的标签上的字段
myWord 是指令作用域上的字段
这个字段上的数据来自于指令所标记的标签(属性名方法的自定义标签)
上的 my-word属性
前提就是:指令作用域上的字段名 = 自定义标签上的属性名- ‘< ’ 作用:
绑定原理同@,
作用是:如果属性值中有插值语法,先运算插值语法的值再把字符串传递过来- ‘=’ 作用:
绑定原理同@
作用是:和外部作用域指定的字段的数据 做了一个双向的数据绑定
link
// link函数参数解析
参数一:指令的作用域
参数二:宿主标签
参数三:宿主标签上的属性
link函数中,参数不受依赖注入的影响,固定顺序固定传参
整个angularjs框架中,link函数常用于操作dom
用的就是elem对象,它是一个JQLite对象,类似以JQuery对象
js代码:
angular.module("s9.app",[])
.directive("myDirective",function(){
var directiveObj = {
template: "<div><input type='text' ng-model='name'></div>",
scope: {
name: "@"
},
link: function(scope,elem,attrs){
elem.find("input")[0].focus(); // 让input标签获取焦点
console.log(attrs['name']); // 结果:tom
}
};
return directiveObj;
})