AngularJs之Scope作用域

前言:

上篇博文AngularJs之directive着说了Scope作用域是单很坑,所以将出去作为重要总结!

什么是scope

  AngularJS
中,作用域是一个对准应用模型的目标,它是表达式的实践环境。作用域有层次结构,这个层次与相应的
DOM 几乎是一致的。作用域能监控表达式和传递事件。

  于
HTML 代码中,一旦一个 ng-app 指令给定义,那么一个作用域就发了,由
ng-app
所杀成的作用域比较独特,它是一个根作用域($rootScope),它是其余有$Scope
的无比暨层。

  除了用
ng-app 指令可以产生一个作用域之外,其他的命令如 ng-controller,ng-repeat
等还见面时有发生一个要基本上个作用域。此外,还可以通过 AngularJS
提供的开创作用域的厂方法来创造一个作用域。这些作用域都具备好的继承上下文,并且根作用域都也$rootScope。

  在转移一个作用域之后,在编制
AngularJS 代码时,$scope
对象就意味着了此作用域的数量实体,我们好于$scope
内定义各种数码类,之后可以一直在 HTML 中坐 {{变量名}} 方式来给 HTML
访问到这个变量。

后续作用域

  AngularJS
在创建一个图域时,会招来上下文,如果前后文中已经存在一个作用域,那么这新创造的作用域就会以
JavaScript 原型继承机制接轨其父作用域的性与道。

  一些
AngularJS
指令会创建新的子作用域,并且进行原型继承: ng-repeat、ng-include、ng-switch、ng-view、ng-controller,
用 scope: true 和 transclude: true 创建的 directive。

  以下
HTML 中定义了三个作用域,分别是由 ng-app
指令所创建的$rootScope,parentCtrl 和 childCtrl 所创建的子作用域,这之中
childCtrl 生成的作用域又是 parentCtrl 的子作用域。

示范一:作用域的持续实例

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args= 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
                $scope.args= 'Nick DeveloperWorks for test';
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args">
    <div ng-controller="childCtrl">
        <input ng-model="args">
    </div>
</div>
</body>
</html>

  继承作用域符合
JavaScript
的原型继承机制,这代表一旦我们于子作用域中访问一个父作用域中定义之习性,JavaScript
首先在子作用域中查找该属性,没找到更起原型链上的父作用域中检索,如果还没找到会重新望上一级原型链的父作用域寻找。在
AngularJS 中,作用域原型链的上方是$rootScope,AnguarJS
将会见寻找到$rootScope 为止,如果要找不交,则会回到 undefined。

  我们因而实例代码说明下这个机制。首先,我们探讨下对原型数据类型的作用域继承机制:

以身作则二:作用域继承实例-原始类型数据持续

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args = 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args">
    <div ng-controller="childCtrl">
        <input ng-model="args">
    </div>
</div>
</body>
</html>

测试运行结果:

第一独输入框:

  虽然当
childCtrl 中莫概念具体的 args 属性,但是盖 childCtrl 的作用域继承自
parentCtrl 的作用域,因此,AngularJS 会找到父作用域中之 args
属性并设置及输入框中。而且,如果我们于第一只输入框中改变内容,内容以会晤共同的影响及第二单输入框。

亚只输入框:

  第二个输入框的内容后将不再跟第一只输入框的情保持并。在转第二个输入框的内容时,因为
HTML 代码中 model 明确绑定以 childCtrl 的图域中,因此 AngularJS 会为
childCtrl 生成一个 args 原始类型属性。这样,根据 AngularJS
作用域继承原型机制,childCtrl 在协调的作用域找得交 args
这个特性,从而为不再会失去追寻 parentCtrl 的 args
属性。从此,两独输入框的情所绑定的习性都是少卖不同的实例,因此无会见再也保持同。

即用代码做如下修改,结合以上两只场景,会面世什么样的结果?

以身作则三:作用域继承实例-对象数据持续

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args = {};
                $scope.args.content = 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args.content">
    <div ng-controller="childCtrl">
        <input ng-model="args.content">
    </div>
</div>
</body>
</html>

测试结果是不管改任何一个输入框的内容,两者的情节尽同。

  根据
AngularJS 的原型继承机制,如果 ng-model 绑定的凡一个目标数据,那么
AngularJS 将非会见吗 childCtrl 创建一个 args 的目标,自然为未见面发
args.content 属性。这样,childCtrl 作用域中将老未会见有 args.content
属性,只能打父作用域中检索,也不怕凡是鲜单输入框的之浮动莫过于只是当反
parentCtrl 作用域中之 args.content
属性。因此,两者的内容一直维持同。

  我们重拘留一个例子,分析结果如何。

演示四:作用域继承实例-不再访问父作用域的多寡对象。

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args = {};
                $scope.args.content = 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
                $scope.args = {};
                $scope.args.content = 'Nick DeveloperWorks for test';
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args.content">
    <div ng-controller="childCtrl">
        <input ng-model="args.content">
    </div>
</div>
</body>
</html>

  测试结果是少数只输入框的情节永远不见面并。子作用域有实例数据对象,则不聘父作用域。

单独作用域

  独立作用域是
AngularJS 中一个可怜出格的作用域,它只是以 directive 中出现。在对
directive 的概念着,我们加加上一个 scope:{} 属性,就为者 directive
创建有了一个断作用域。

示范5: directive 创建有一个孤立作用域

angular.module('isolate', []).directive("isolate", function () {
 return {
 scope : {},
 };
})

  独立作用域最老之风味是休见面原型继承其父作用域,对外边的父作用域保持相对的独。因此,如果当概念了孤立作用域的
AngularJS directive 中想要拜访该父作用域的性质,则获的价也
undefined。代码如下:

示例六:独立作用域的隔离性

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('ctrl', ['$scope', function($scope) {
                $scope.args = {};
            }])
            .directive("isolateDirective", function () {
                return {
                    scope : {},
                    link : function($scope, $element, $attr) {
                        console.log($scope.$args); //输出 undefined
                    }
                };
            });
</script>
<body ng-app="app">
<div ng-controller="ctrl">
    <div isolate-directive></div>
</div>
</body>
</html>

  上面的代码中通过在
directive 中宣称了 scope 属性从而创造了一个作用域,其父作用域为 ctrl
所属之作用域。但是,这个作用域是孤立的,因此,它访问不至父作用域的负的其余性质。存在这么设计编制的益处是:能够创造有有些排可复用的
directive,这些 directive
不会见彼此以颇具的属于性值上闹串扰,也非见面发出其他副作用。

AngularJS 独立作用域的数量绑定

  在后续作用域中,我们得选取子作用域直接操作父作用域数据来促成父子作用域的通信,而在单独作用域中,子作用域不可知直接访问和改动父作用域的习性和价值。为了能使孤立作用域也会同外围通信,AngularJS
提供了三栽方法因此来打破独立作用域“孤立”这同样限制。

一面绑定(@ 或者 @attr)

  这是
AngularJS
独立作用域与外面父作用域进行数量通信中极简便的相同种,绑定的靶子只能是父作用域中的字符串值,并且也就为只读引用,无法对父作用域中之字符串值进行修改,此外,这个字符串还须以父作用域的
HTML 节点受到因为 attr(属性)的方宣示。

  使用这种绑定方式时,需要以
directive 的 scope 属性中明显指定引用父作用域中之 HTML
字符串属性,否则会丢掉大。示例代码如下:

实例七: 单向绑定示例

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script>
    angular.module('isolateScope', [])
            .directive("isolateDirective", function () {
                return {
                    replace : true,
                    template: '<button>{{isolates}}</button>',
                    scope : {
                        isolates : '@',
                    },
                    link : function($scope, $element, $attr) {
                        $scope.isolates = "DeveloperWorks";//无效
                    }
                };
            })
            .controller("ctrl", function ($scope) {
                $scope.btns = 'NICK';
            });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
    <button>{{btns}}</button>
    <div isolate-directive isolates="{{btns}}"></div>
</div>
</body>
</html>

  上面的代码,通过在
directive 中宣示了 scope:{isolates:’@’} 使得 directive 拥有了父作用域中
data-isolates (isolates为自定义属性,不加data也足以,但建议加上data)这个
HTML 属性所怀有的价,这个价当控制器 ctrl
中让赋值为’nick’。所以,代码的周转结果是页面上有点儿只称呼吧
nick的按钮。

  我们还在意到
link 函数中对 isolates
进行了改动,但是最后不会见于运作结果中体现。这是坐 isolates
始终绑定为父作用域中的 btns 字符串,如果父作用域中之 btns
不更改,那么当孤立作用域中管怎么改 isolates 都不见面从作用。

援绑定(&或者&attr)

  通过这种样式的绑定,孤立作用域将起能力看到父作用域中之函数对象,从而能实践父作用域中之函数来取得某些结果。这种方法的绑定跟单向绑定一样,只能坐仅读之点子访父作用函数,并且这函数的概念必须写在父作用域
HTML 中之 attr(属性)节点上。

  这种办法的绑定虽然无法修改父作用域的
attr
所设定的函数对象,但是也足以由此执行函数来改变父作用域中或多或少性能的值,来达成一些预料的意义。示例代码如下:

示例八:引用绑定示例

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script>
    angular.module('isolateScope', [])
            .directive("isolateDirective", function () {
                return {
                    replace : true,
                    scope : {
                        isolates : '&',
                    },
                    link : function($scope, $element, $attr) {
                        var func = $scope.isolates();
                        func();
                    }
                };
            })
            .controller("ctrl", function ($scope) {
                $scope.func = function () {
                    console.log("Nick DeveloperWorks");
                }
            });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
    <div isolate-directive data-isolates="func"></div>
</div>
</body>
</html>

  这个例子中,浏览器的控制台将会晤打印“Nick
DeveloperWorks”文字。

  上面的代码中我们于父作用域中指定了一个函数对象$scope.func,在孤立作用域中经过对
HTML 属性的绑定从而引用了 func。需要留意的凡 link 函数中针对 func
对象的采取方式,$scope.isolates
获得的特是函数对象,而未是调用这个目标,因此我们得以调用完$scope.isolates
之后又调用这个函数,才会获得实在的履行结果。

双向绑定(=或者=attr)

双向绑定赋予
AngularJS
孤立作用域与外界最自由之双向数据通信功能。在双向绑定模式下,孤立作用域能够一直读写父作用域中之性与多少。和上述两种植孤立作用域定义数据绑定一样,双向绑定也亟须以父作用域的
HTML 中设定属性节点来绑定。

双向绑定好适用于有子
directive
需要数与父作用域进行数量交互,并且数据比较复杂的气象。不过,由于足无限制的读写父作用域中之习性与目标,所以当局部大抵单
directive
共享父作用域数据的场面下需要小心使用,很轻滋生数据达的紊乱。

以身作则代码如下:

示例九:双向绑定示例

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script>
    angular.module('isolateScope', [])
            .directive("isolateDirective", function () {
                return {
                    replace : true,
                    template: '<button>{{isolates}}</button>',
                    scope : {
                        isolates : '=',
                    },
                    link : function($scope, $element, $attr) {
                        $scope.isolates.name = "NICK";
                    }
                };
            })
            .controller("ctrl", function ($scope) {
                $scope.btns = {
                    name : 'nick',
                    dw : 'DeveloperWorks'
                };
            });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
    <button>{{btns.dw}}</button>
    <button>{{btns.name}}</button>
    <div isolate-directive data-isolates="btns"></div>
</div>
</body>
</html>

  上面的代码运行的结果是浏览器页面上起三独按钮,其中第一单按钮标题为“DeveloperWorks”,第二跟老三只按钮的题目为“NICK”。

始于时父作用域中的$scope.btns.name为多少写的“nick”,通过双向绑定,孤立作用域中将父作用域的
name改写成为大写的“NICK”并且一直生效,父作用域的值为改变。

  推荐:当即首关于作用域的稿子也罢勾勒的不错,可以望!

 

相关文章