scope参数有以下几种方式:
1,不填,默认为scope:false
2,scope:true
3,scope:{}
4,
scope:{ name: ‘=‘, age: ‘@‘, say: ‘&‘ }
下面我来分别说明他们之间的用法:
第一种:看代码
<script> angular module(‘exampleApp‘, []) .controller(‘scopeCtrl‘, function ($scope) { // do something }); .directive(‘scopeDome‘, function () { return { template: "<div class=‘body‘>Name:<input ng-model=‘name‘></div>" } }) </script>
这里没有对scope做定义,则angular会调用默认值(scope:false),这时指令中的作用域即是其父级所处的作用域,这里可以调用到父级作用中的变量和方法;
如:
<script type="text/javascript"> angular.module("exampleApp", []) .directive("scopeDemo", function () { return { template: function() { return angular.element( document.querySelector("#scopeTemplate")).html(); }, link: function (scope, element, attrs) { scope.func(); // 调用父级控制器里的方法; } } }) .controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam" }; $scope.city = "London"; $scope.func = function () { alert(‘you can call me!‘); } }); </script>
第二种:看代码
js部分:
<script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <p>Name: <input ng-model="data.name" /></p> <p>City: <input ng-model="city" /></p> <p>Country: <input ng-model="country" /></p> </div> </script> <script type="text/javascript"> angular.module("exampleApp", []) .directive("scopeDemo", function () { return { template: function() { return angular.element( document.querySelector("#scopeTemplate")).html(); }, scope: true, link: function (scope, element, attrs) { scope.func(); } } }) .controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam" }; $scope.city = "London"; $scope.func = function () { alert(‘ok‘); } });</script>
HTML部分
<body ng-controller="scopeCtrl"> <div class="panel panel-default"> <div class="panel-body" scope-demo></div> <div class="panel-body" scope-demo></div> </div> </body>
在HTML中有两处调用了这个指令,但生产的效果是不太一样的,在运行时
效果是,Name是同步的(上下改变任何一个另一个都会跟着变),City和Country却是独立的,上下两个改变都不会影响到另外一个;
原因是scope:true允许我们在同一个控制器中创造一个新作用域,但这个作用域是可以继承其父级的作用域的属性和方法的,那么是不是跟没写scope一样了,其实不然,因为他毕竟创造了自己的作用域,那么他的自由性就会比没写scope强,那么为什么有的能动态一起变,有的不能呢,那就看看他们的数据属性吧:
<div class="panel-body"> <p>Name: <input ng-model="data.name" /></p> <p>City: <input ng-model="city" /></p> <p>Country: <input ng-model="country" /></p> </div>在控制器中:
.controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam" }; $scope.city = "London"; $scope.func = function () { alert(‘ok‘); } });
名称 | 描述 |
data.name | 这个属性是在一个对象上定义的,意味着这个值将会在指令中的各个实例之间共享,而且所有绑定到该属性的输入框元素将会保持同步 |
city | 这个属性是在控制器的作用域上直接被赋值的,意味着指令所有的作用域将会从同一个初始值开始,但是在输入框元素被修改时会在自己的作用域上创建和修改自己的版本 |
country | 这个属性没有被赋任何值,当相应的输入框元素被修改时, 指令的每个实例将会创建出独立的county属性。 |
第三种:看代码
<script type="text/javascript"> angular.module("exampleApp", []) .directive("scopeDemo", function () { return { template: function() { return angular.element( document.querySelector("#scopeTemplate")).html(); }, scope: {} } }) .controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam" }; // 这两个方法将不能传到指令中,供指令使用 $scope.city = "London"; }); </script>
scope:{} 表示告诉angular这个指令要创建一个独立(隔离)的作用域,这样这个独立的作用域就不能继承外界的父级控制器的作用域。这样的好处是指令在复用时不会污染到外界的父级作用域。
第四种
第四种是第三种方式的强化,即虽然我的作用域与外界隔离了,但有一些参数(数值,属性,方法)还是想从外界获得。那么该如何获得呢,
angular提供了三种方法供我们使用,分别是 ‘=’、 ‘@’、 ‘&’, 他们的作用分别是:
@: 通过属性值进行绑定,但是单向的,即外界控制器可以把值传进来供内部使用,但内部对这个属性值进行修改时不会影响到外部的;
js部分
<script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <p>Data Value: {{local}}</p> </div> </script> <script type="text/javascript"> angular.module("exampleApp", []) .directive("scopeDemo", function () { return { template: function() { return angular.element( document.querySelector("#scopeTemplate")).html(); }, scope: { local: "@nameprop" } } }) .controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam" }; }); </script>
HTML部分
<body ng-controller="scopeCtrl"> <div class="panel panel-default"> <div class="panel-body"> Direct Binding: <input ng-model="data.name" /> // 这里改变下面会跟着改变 </div> <div class="panel-body" scope-demo nameprop="{{data.name}}"></div> // 跟着上面数值动态变化 </div> </body>
指令中的local通过nameprop获得外部属性data.name,所以在控制器中的data.name变化时,指令中的local也会跟着改变;(但如果是只改变local的值,外界的data.name是不会变的);
=: 通过属性进行双向数据绑定,内外变化会保持一致;
js部分
<script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <p>Data Value: <input ng-model="local" /></p> </div> </script> <script type="text/javascript"> angular.module("exampleApp", []) .directive("scopeDemo", function () { return { template: function() { return angular.element( document.querySelector("#scopeTemplate")).html(); }, scope: { local: "=nameprop" } } }) .controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam" }; }); </script>
HTML部分
<body ng-controller="scopeCtrl"> <div class="panel panel-default"> <div class="panel-body"> Direct Binding: <input ng-model="data.name" /> </div> <div class="panel-body" scope-demo nameprop="data.name"></div> </div> </body>
显示的效果:
指令和控制器双方通过 local: "=nameprop" 进行双向数据绑定;
&: 调用父级作用域中的方法(function);
js部分
<script type="text/ng-template" id="scopeTemplate"> <div class="panel-body"> <p>Name: {{local}}, City: {{cityFn()}}</p> </div> </script> <script type="text/javascript"> angular.module("exampleApp", []) .directive("scopeDemo", function () { return { template: function () { return angular.element( document.querySelector("#scopeTemplate")).html(); }, scope: { local: "=nameprop", cityFn: "&city" } } }) .controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam", defaultCity: "London" }; $scope.getCity = function (name) { return name == "Adam" ? $scope.data.defaultCity : "Unknown"; } }); </script>
HTML部分
<body ng-controller="scopeCtrl"> <div class="panel panel-default"> <div class="panel-body"> Direct Binding: <input ng-model="data.name" /> </div> <div class="panel-body" scope-demo city="getCity(data.name)" nameprop="data.name"></div> </div> </body>
city特性的值是一个表达式,调用了getCity行为并将data.name属性作为参数传入进行处理。要使这个表达式在隔离作用域中可用,在scope中添加 cityFn: "&city",前缀‘&’就告诉angular,我想将所指定特性的值(cityFn)绑定到一个函数,剩下就是在指令中调用这个函数表达式了:{{cityFn()}}
PS:这里所有指令作用域跟外界交互都是通过属性值传入的:<div class="panel-body" scope-demo city="getCity(data.name)" nameprop="data.name"></div>