scope选项
<pre>
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#div1 div{
width: 200px;
height:200px;
border: 1px solid red;
display: none;
}
#div1 input.active{
background-color: red;
}
</style>
<script src="js/angular.min.js"></script>
<script type="text/javascript">
var m1= angular.module("myApp",[]);
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
templateUrl:'temp1.html'
};
});
m1.controller('Aaa',['$scope',function($scope){
$scope.name= 'hello';
}]);
</script>
</head>
<body ng-controller="Aaa">
<my-tab></my-tab>
<!--指令的最大特点是可以复用的-->
<!--<my-tab></my-tab>-->
<!--在此标签上重新初始化name变量的值,由"hello" 改为 "hi"-->
<my-tab ng-init="name ='hi'"></my-tab>
</body>
</html>
</pre>
temp1.html
<pre>
<div id="div1">
<input type="button" value="1" class="active"/>
<input type="button" value="2"/>
<input type="button" value="3"/>
<div style="display: block">{{name}}</div>
<div>22222</div>
<div>33333</div>
</div>
</pre>
运行结果如下图:
分析:
1. myTab标签指令中的表达式的值变成“hi”,其实说明这个变量的查找是从内向外的,和作用域的方式是一样的。
2. 所以先找到的name值是<my-tab ng-init="name ='hi'">
这个标签上的name值,即“hi”;如果没找到,就继续往外找,找到body当中,从而找到“hello”。
所以第二个tab标签中显示的值是“hi”,这是正确的;但有问题的是:第一个tab标签中显示的值也变成“hi”,即第二个tab标签的name值修改会影响到第一个tab标签的值的显示。
即说明默认情况下,这两个tab标签是共享作用域的。
问题:自定义标签在不同环境下、不同页面或者不同标签结构中,这时候如果所有的数据都是共享的,除非实现的功能是一模一样的,要不然就很麻烦了,扩展性会非常大。
解决办法:angularJs为自定义指令提供了一个scope选项,可以解决上述提到的问题。
1.scope独立作用域
默认为false,将scope设置为true,代表当前标签指令具备独立作用域
每一个标签指令中的作用域都是独立的,不会互相影响。
修改myTab标签指令如下:
<pre>
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
scope:true,
templateUrl:'temp1.html'
};
});
</pre>
运行结果如下图所示:
但是,即使有独立作用域,还是能继承父级的数据。父级数据还是会影响子级的数据。
2.scope隔离作用域
可以使本层作用域不会与外层作用域有任何的瓜葛,只在当前标签指令内部单独起作用。
书写方式:
<pre>
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
scope:{},<!-- 将scope值设置为“{}”,即代表隔离作用域-->
templateUrl:'temp1.html'
};
});
</pre>
此时的运行结果如下图所示:
原因分析:
controller中的name($scope.name= 'hello';
)是属于外层作用域的变量,myTab标签上的name<my-tab ng-init="name ='hi'">
,也是属于外层作用域的变量;
所示标签内部的表达式{{name}}
被隔离了,不能找到外部作用域下的数据了。
那么问题又来了,如何在标签指令的模板中绑定数据呢?
controller选项
angularJS的自定义指令中提供了一个controller选项,用来为模板绑定数据。
书写方式与普通的controller的类似。
代码如下所示:
<pre>
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#div1 div{
width: 200px;
height:200px;
border: 1px solid red;
display: none;
}
#div1 input.active{
background-color: red;
}
</style>
<script src="js/angular.min.js"></script>
<script type="text/javascript">
var m1= angular.module("myApp",[]);
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
scope:{},
controller:["$scope",function($scope){
$scope.name="good";
}],
templateUrl:'temp1.html'
};
});
m1.controller('Aaa',['$scope',function($scope){
$scope.name= 'hello';
}]);
</script>
</head>
<body ng-controller="Aaa">
<my-tab></my-tab>
<my-tab ng-init="name ='hi'"></my-tab>
</body>
</html>
</pre>
运行结果如下图所示:
可以发现,自定义指令中的controller定义的数据,对于同一个指令是共享的。
还有,一直存在的一个问题,同一个指令标签多次调用,模板中的<div id="div1">
id会重复。
那么像这种有差异的数据如何体现呢?
angularJs也是通过scope来解决,准确的说是依据scope的绑定策略来解决。
scope的绑定策略
“@”
作用:指定到底是谁变成了参数,并且这个参数的值是普通的字符串。
<pre>
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
scope:{
<!--完整写法是:myId:'@myId',但是如果变量名是相同的,可以省略;若不同,则不能 -->
myId:'@'
},
templateUrl:'temp1.html'
};
});
......
<body ng-controller="Aaa">
<my-tab my-id="div1"></my-tab>
<my-tab my-id="div2"></my-tab>
</body>
</pre>
temp1.html
<pre>
<div id="{{myId}}">
<!-- <div id="div1"> -->
<input type="button" value="1" class="active"/>
<input type="button" value="2"/>
<input type="button" value="3"/>
<div style="display: block">{{name}}</div>
<div>22222</div>
<div>33333</div>
</div>
</pre>
运行结果如下图所示:
从图中可以看出:两个指令标签生成的id就变成不同的了,绑定策略成功了。
若scope绑定的变量名不同时,代码如下:
<pre>
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
scope:{
<!--完整写法是:myId:'@myId',但是如果变量名是相同的,可以省略;若不同,则不能 -->
myId:'@aaa'
},
templateUrl:'temp1.html'
};
});
......
<body ng-controller="Aaa">
<my-tab aaa="div1"></my-tab>
<my-tab aaa="div2"></my-tab>
</body>
</pre>
temp1.html
<pre>
<div id="{{myId}}">
<!-- <div id="div1"> -->
<input type="button" value="1" class="active"/>
<input type="button" value="2"/>
<input type="button" value="3"/>
<div style="display: block">{{name}}</div>
<div>22222</div>
<div>33333</div>
</div>
</pre>
运行效果与上图相似。
“=”
作用:指定到底是谁变成了参数,并且这个参数的值是一个可解析的数据,即变量。
<pre>
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#div1 div,
#div2 div{
width: 200px;
height:200px;
border: 1px solid red;
display: none;
}
#div1 input.active,
#div2 input.active{
background-color: red;
}
</style>
<script src="js/angular.min.js"></script>
<script type="text/javascript">
var m1= angular.module("myApp",[]);
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
scope:{
myId:'@aaa',
myName:'='
},
controller:["$scope",function($scope){
$scope.name="good";
}],
templateUrl:'temp1.html'
};
});
m1.controller('Aaa',['$scope',function($scope){
$scope.name= 'hello';
}]);
</script>
</head>
<body ng-controller="Aaa">
<my-tab aaa="div1" my-name="name"></my-tab>
<my-tab aaa="div2" my-name="name"></my-tab>
</body>
</html>
</pre>
temp1.html
<pre>
<div id="{{myId}}">
<!-- <div id="div1"> -->
<input type="button" value="1" class="active"/>
<input type="button" value="2"/>
<input type="button" value="3"/>
<div style="display: block">{{myName}}</div>
<div>22222</div>
<div>33333</div>
</div>
</pre>
运行结果如下图所示:
从图中可以看出,此时{{myName}}
解析出来的是”Aaa”controller中定义的name值。
“&
”
作用是:绑定父级函数的一种传递传递方式。
<pre>
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#div1 div,
#div2 div{
width: 200px;
height:200px;
border: 1px solid red;
display: none;
}
#div1 input.active,
#div2 input.active{
background-color: red;
}
</style>
<script src="js/angular.min.js"></script>
<script type="text/javascript">
var m1= angular.module("myApp",[]);
m1.directive("myTab",function(){
return{
restrict:"E",
replace:true,
scope:{
myId:'@aaa',
myName:'=',
myFn:'&'
},
controller:["$scope",function($scope){
$scope.name="good";
}],
templateUrl:'temp1.html'
};
});
m1.controller('Aaa',['$scope',function($scope){
$scope.name= 'hello';
$scope.show = function (num){
alert(num);
}
}]);
</script>
</head>
<body ng-controller="Aaa">
<!--此时`my-fn="show(num)"`中的值只是字符串,还没有传值-->
<my-tab aaa="div1" my-name="name" my-fn="show(num)"></my-tab>
<my-tab aaa="div2" my-name="name" my-fn="show(num)"></my-tab>
</body>
</html>
</pre>
temp1.html:
<pre>
<div id="{{myId}}">
<!--此时myFn被调用,才需要传实参-->
<input type="button" value="1" class="active" ng-click="myFn({num:456})"/>
<input type="button" value="2"/>
<input type="button" value="3"/>
<div style="display: block">{{myName}}</div>
<div>22222</div>
<div>33333</div>
</div>
</pre>
运行结果如下: