当angularjs指令创建时面临的一个问题就是作用域的创建,也就是指令的scope。
angularjs提供了三种选择,体现在定义指令时的scope参数上,true,false,{}. 默认false;
scope = false
看代码
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="bootstrap.min.css">
<script src="angular.min.js"></script>
<script src="bootstrap.min.js"></script>
<script type="text/javascript">
var myapp = angular.module("myapp", []);
myapp.controller("MyController", ['$scope', function($scope) {
$scope.name = "mario";
}]);
myapp.directive("myDirective", function() {
return {
restrict: "AE",
scope: false,
replace: true,
template: "<div>" +
"<h1>下面部分是创建的指令生成的</h1>" +
"我的名字是:<span ng-bind='name'></span><br/>" +
"<input type='text' ng-model='name'><br/>" +
" </div>"
}
});
</script>
</head>
<body ng-app="myapp">
<div class="container" ng-controller="MyController">
<div>
我的名字是:<span ng-bind="name"></span>
<br/>
<input type="text" ng-model="name" />
</div>
<div my-directive></div>
</div>
</body>
</html>
scope = true
将上面false改为true, 可以发现,父作用域name改变,指令scope中的name改变,当然这有一个前提,那就是你还没去改变过指令scope中name的值。一旦改变就不起作用了。 而当你先去改变指令scope中的值可以发现父作用域中的name并没有改变。可以理解为指令创建了一个新的作用域,并且使用父scope中的值初始化了其中的值,而这个可以一直持续到你去改变指令scope中变量de值。
scope = {}
当我们将
scope
设置为
{}
时,意味着我们创建的一个新的与父作用域隔离的新的作用域,这使我们在不知道外部环境的情况下,就可以正常工作,不依赖外部环境。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="bootstrap.min.css">
<script src="angular.min.js"></script>
<script src="bootstrap.min.js"></script>
<script type="text/javascript">
var myapp = angular.module("myapp", []);
myapp.controller("MyController", ['$scope', function($scope) {
$scope.name = "mario";
$scope.age = 23;
$scope.changeAge = function() {
$scope.age = 19;
}
}]);
myapp.directive("myDirective", function() {
return {
restrict: "AE",
scope: {
name : '@myName',
age : '=age',
change : '&change'
},
replace: true,
template: "<div>" +
"<h1>下面部分是创建的指令生成的</h1>" +
"我的名字是:<span ng-bind='name'></span><br/>" +
"<input type='text' ng-model='name'><br/>" +
"我的age是:<span ng-bind='age'></span><br/>" +
"<input type='text' ng-model='age'><br/>" +
"<button class='btn btn-small btn-primary' ng-click='change()'>修改年龄</button>" +
" </div>"
}
});
</script>
</head>
<body ng-app="myapp">
<div class="container" ng-controller="MyController">
<div>
我的名字是:<span ng-bind="name"></span>
<br/>
<input type="text" ng-model="name" />
<br/>
我的age是:<span ng-bind="age"></span>
<br/>
<input type="text" ng-model="age" />
</div>
<div my-directive my-name="{{name}}" age="age" change="changeAge()"></div>
</div>
</body>
</html>
使用了隔离的作用域,不代表我们不可以使用父作用域的属性和方法。
- 我们可以通过向
scope
的{}
中传入特殊的前缀标识符(即prefix
),来进行数据的绑定。 - 创建了隔离的作用域,我们可以通过
@
,&
,=
引用应用指令的元素的属性,如上面的代码那样,我们可以在scope: {
name : '@myName',
age : '=age',
change : '&change'
} 中,利用前缀标识符引用<div my-directive my-name="{{name}}" age="age" change="changeAge()"></div>中my-name, change,age
这些属性的值。
下面我们来看看如何使用这些前缀标识符:
@
这是一个单项绑定的前缀标识符
使用方法: @myName驼峰写法对应my-name属性中的{{name}}, {{}}不可少,name是父scope中的模型
注意,属性的名字要用-
将两个单词连接
=
这是一个双向数据绑定前缀标识符
使用方法:写法和上面差不多,不需要{{}}
另外,如果指令scope参数中key:value 同名可省略
上面的scope: {
name : '@myName',
age : '=age',
change : '&change'
}
也可以写成
scope: {
name : '@myName',
age : '=',
change : '&'
}
my-name以及age属性也可以跟普通字符串,那么指令scope中模型也将被赋予相应de属性值。
&
这是一个绑定函数方法的前缀标识符
使用方法: 需要注意的是属性值写成调用方法的形式,change="changeAge()"
进一步说明,我们的指令是如何利用这些前缀标识符来寻找我们想要的属性或者函数的
@
当指令编译到模板的name
时,就会到scope
中寻找是否含有name
的键值对,如果存在,就像上面那样,看到@
就知道这是一个单向的数据绑定,然后寻找原来的那个使用指令的元素上(或者是指令元素本身)含有这个值的属性即my-name={{name}}
,然后在父作用域查找{{name}}
的值,得到之后传递给模板中的name
。=
和&
与@
差不多,只不过=
进行的是双向的数据绑定,不论模板还是父作用域上的属性的值发生改变都会使另一个值发生改变,而&
是绑定函数而已。
在附带一个&中函数有参数时的调用
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="bootstrap.min.css">
<script src="angular.min.js"></script>
<script src="bootstrap.min.js"></script>
<script type="text/javascript">
var myapp = angular.module("myapp", []);
myapp.controller("MyController", ['$scope', function($scope) {
$scope.name = "mario";
$scope.age = 23;
$scope.changeAge = function(age) {
$scope.age = age;
}
}]);
myapp.directive("myDirective", function() {
return {
restrict: "AE",
scope: {
name : '@myName',
age : '=',
change : '&'
},
replace: true,
template: "<div>" +
"<h1>下面部分是创建的指令生成的</h1>" +
"我的名字是:<span ng-bind='name'></span><br/>" +
"<input type='text' ng-model='name'><br/>" +
"我的age是:<span ng-bind='age'></span><br/>" +
"<input type='text' ng-model='age'><br/>" +
"<button class='btn btn-small btn-primary' ng-click='change({s:19})'>修改年龄</button>" +
" </div>"
}
});
</script>
</head>
<body ng-app="myapp">
<div class="container" ng-controller="MyController">
<div>
我的名字是:<span ng-bind="name"></span>
<br/>
<input type="text" ng-model="name" />
<br/>
我的age是:<span ng-bind="age"></span>
<br/>
<input type="text" ng-model="age" />
</div>
<div my-directive my-name="{{name}}" age="age" change="changeAge(s)"></div>
</div>
</body>
</html>