scope in Angularjs

scope基于原型的继承性

视图存在嵌套的时候,内层的controller是可以继承到外层的controller数据的。

scope在angularjs里的继承性(基于原型的继承性):

    html: 
    
    <div ng-controller="MainController">
        Parent <input type='text' ng-model="info"> {{info}}
        <div ng-controller="subController">
            child <input type='text' ng-model="info"> {{info}}
        </div>
    </div>

当页面一开始加载完毕之后,通过在parentinput里面输入内容的时候,在childinput里面也会发生响应。这个时候,subController里的info的值,是继承parent里面的mainController的值。

此时,如果在childinput里面输入内容,会发现child里面的info发生了变化,但是parent里面并未发生变化。

此时如果在parentInput里面输入值的话,仅仅是Parentinfo发生了变化,而childinfo是不会发生变化的。

然后我再换一种写法

    html:
   
    <div ng-controller="mainController">
        parent <input type="text" ng-model='msg.info'> {{msg.info}}
            <div ng-controller="subController">
                child <input type="text" ng-model="msg.info"> {{msg.info}}
            </div>
    </div>
    
    js: 
    app.controller('mainController', function(){
        $scope.msg = {
            info: 'message'
        };
    });
    app.controller('subController', function(){
        
    });

ng-model此时变成了某个对象的属性。那么现在不管你更改的是parent中的input还是child中的input,都会引起视图相应的变化。

这2者的区别就是在subController中继承了mainController中的作用域。当ng-modelprimitive值时,刚初始化的时候,在subController里面因为,会新建一个相同的变量,这个时候,如果再在subController里面获取这个primitive的时候,就直接在subController里面就能得到。

而如果mainController里面的ng-model是个对象的属性的时候,subController里面ng-model是对这个对象的引用。那么不管更改mainController还是subController里面的ng-model视图里面都会发生变化。

在Angularjs里面$scope有个$watch方法,当需要时更新DOM。通过监听某个model的是否发生变化来触发相应的callback

依然是上面的例子:

     html:
   
    <div ng-controller="mainController">
        parent <input type="text" ng-model='msg.info'> 
    </div>
    
    js: 
    app.controller('mainController', function(){
        $scope.msg = {
            info: 'message'
        };
        
        $scope.$watch('msg', function(val){
            console.log(val);
        })
    });

除了页面初始化后,控制台会输出{info: 'message'}外,不过input里面的值如何变化。控制台都不会输出任何内容了。这是因为$watch是比较的msg这个对象的引用是否发生了变化,很显然这个地方msg的引用(heap里面存放的地址)并没用发生变化,仅仅是msg.info的值发生了变化。
但是我改变另外一种写法:

    $scope.$watch('msg', function(val){
        console.log(val);
    }, true);

这个是否就能监听到msg.info发生变化后,msg的内容了。第三个属性boolean值,当为true,规定的是比较对象的值,而不是引用。

ng-repeat会给每个循环新建一个作用域。

ng-includeng-view都是动态加载视图,这个时候也会新建作用域

当然还有ng-switch,directive也会有这种scope继承的情况出现。

具体深入理解angularjsscope,请移步Understanding scopes

Angularjs 1.2 “Controller as” polyfill

    html:
    
    <div ng-controller='parentController as parent'>
        {{parent.name}}
        <div ng-controller='childController as child'>
            {{child.name}}
        </div>
    </div>
    
    js:
    
    app.controller('parentController', ApiParentFn);
    
    function ApiCtrlFn(){
        this.name = 'XL';
    }
    
    app.controller('childController', ApiChildFn);
    
    function ApiChildFn(){
        this.name = 'xl';
    }

最后视图内容大家可以动手试试。

最近也试着多用这个语法去写控制器,首先写法上更偏向OO的风格。在这个ApiParetnFn上定义不同的model。

    app.controller('mainCtrl', ['$http', ApiCtrlFn]);
    
    function ApiCtrlFn(http){
        this.http = http;
        this.name = 'XL';
    }
    
    ApiCtrlFn.prototype = {
        reqPostFn: function(url){
            this.http.get(url).success(function(data){
                xxxx
            })
            .error(function(data){
                xxxx
            })
        },
        changeNameFn: function(name){
            this.name = name;
        }
    }
    
    html:
    
    <div ng-controller="mainCtrl as main">
        {{this.name}}
        <button ng-click="main.changeNameFn('xl')"></button>
    </div>

ApiParentFn.prototype上定义不同的方法。这样可以非常好的将一些可服用的代码抽离出来。不同的控制器只需要对构造函数进行实例化,然后调用不同的原型上定义的方法就OK了。

    原文作者:苹果小萝卜
    原文地址: https://segmentfault.com/a/1190000004056830
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞