美文网首页
AngularJs作用域高级特性,作用域属性监视、digest循

AngularJs作用域高级特性,作用域属性监视、digest循

作者: TryCatch菌 | 来源:发表于2019-07-10 11:17 被阅读0次

    AngularJs作用域高级特性,作用域属性监视、digest循环等

    基于AngularJS入门与进阶(江荣波 著)这本书的笔记

    AngularJS 1.x的demo

    AngularJS1.x和Angular2,4,5是不一样的两个东西,构建方式,语法,都很多不同


    $watch方法监视作用域

    在传统的JavaScript中如果要监视一个方法是比较繁琐的事情,不过在AngularJs中可以使用$watch 对对像进行手工监视,让对像发生变化的时候触发

    $watch(watchFn,watchAction,deepWatch)
    
    • watchFn:angular表达式或函数的字符串
    • watchAction(newValue,oldValue,scope):watchFn发生变化会被调用
    • deepWatch:可选的布尔值命令检查被监控的对象的每个属性是否发生变化

    示例代码

    <!DOCTYPE html>
    <html lang="en" ng-app="scopeApp">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script  src="/lib/angular/angular.js"></script>
        <script type="text/javascript">
            var scopeApp = angular.module("scopeApp",[]);
            scopeApp.controller("scopeController",function ($scope,$log) {
                $scope.changeNum = 0;
                $scope.$watch('userName',function (newValue,oldValue) {
                    ++$scope.changeNum;
                    console.log("newValue:" + newValue + " " + "oldValue:" + oldValue + " " + "changeNum:" + $scope.changeNum);
                });
            });
        </script>
    </head>
    <body >
        <div ng-controller="scopeController">
            <input ng-model="userName" type="text">
            <span>改变次数:{{changeNum}}</span>
        </div>
    </body>
    </html>
    

    控制台输出

    newValue:undefined oldValue:undefined changeNum:1
    newValue:2 oldValue:undefined changeNum:2
    newValue:23 oldValue:2 changeNum:3
    newValue:231 oldValue:23 changeNum:4
    newValue:2314 oldValue:231 changeNum:5
    

    从控制台输出可以看出,才进去的时候新的值和旧的值都是未定义,改变次数为1,当在文本框录入一次值后,新的值变为2,旧值是未定义,改变次数为2,再次输入新值变为23,旧值变为2,改变次数为3。通过这个方法我们能很简便的监控某些特定的值或者字段。

    需要注意的是,示例代码中$watch只用了两个参数,如果不定义第三个参数,默认为false,不会监控引用数据类型例如数组等类型的变化。如果需要监控引用数据类型,需要显式定义为true,就可以实现监控。

    在angular 1.1.4版本之后,新增加了一个$watchCollection()方法来针对数组(也就是集合)进行监视,它的性能介于全等监视和引用监视之间,即它并不会对数组中每一项的属性进行监视,但是可以对数组的项目增减做出反应。

    对于多个变量的监视变化,执行同一函数的话,可以将这几个变量转为字符串,以‘+’号隔开来进行监视

    $scope.$watch('count + page',function(){
    ...
    });
    
    作用域监视解除

    如果在某种特定的条件下需要解除监视,可以调用unbindWatcher();方法

    var scopeApp = angular.module("scopeApp",[]);
            scopeApp.controller("scopeController",function ($scope,$log) {
                $scope.changeNum = 0;
                // $watch 回调函数可以解除监视
                var unbindWatcher = $scope.$watch('userName',function (newValue,oldValue) {
                    ++$scope.changeNum;
                    console.log("newValue:" + newValue + " " + "oldValue:" + oldValue + " " + "changeNum:" + $scope.changeNum);
                    if($scope.changeNum == 3){
                        unbindWatcher();
                    }
                });
            });
    

    示例代码样式在改变次数到3后,就不会再出发watch方法了

    newValue:undefined oldValue:undefined changeNum:1
    newValue:2 oldValue:undefined changeNum:2
    newValue:22 oldValue:2 changeNum:3
    
    $apply$digest

    在AngularJS作用域中的数据发生变化时,会自动触发digest循环,从而达到自动更新视图,实现数据的双向绑定。不过如果我们在angularjs中使用了原生的javascript改变了作用域中的值,是不会更新视图的,这个时候就需要手动调用`apply来触发 $digest`。

    示例代码,就是书中的代码,使用setTimeout的JS触发,可以发现控制台输出了改变的值,但是视图中没有改变

    <!DOCTYPE html>
    <html lang="en" ng-app="scopeApp">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script  src="/lib/angular/angular.js"></script>
        <script type="text/javascript">
            var scopeApp = angular.module("scopeApp",[]);
            scopeApp.controller("scopeController",function ($scope,$log) {
                $scope.userName = '初始姓名';
                console.log("姓名" + $scope.userName);
                $scope.clickTest = function () {
                    // js 延时触发
                    setTimeout(function () {
                        $scope.userName = '改变姓名';
                        console.log("改变姓名" + $scope.userName);
                    },1000);
                }
            });
        </script>
    </head>
    <body >
    <div ng-controller="scopeController">
        <input value="点击测试" type="button" ng-click="clickTest()"><br/>
        <span>姓名:{{userName}}</span>
    </div>
    </body>
    </html>
    
    image.png

    代码修改一下,能成功触发

    $scope.clickTest = function () {
                    // js 延时触发
                    setTimeout(function () {
                        // 使用apply手工触发digest
                        $scope.$apply(function () {
                            $scope.userName = '改变姓名';
                            console.log("改变姓名" + $scope.userName);
                        });
                    },1000);
                }
    
    image.png
    $timeout$interval服务介绍

    JavaScript的setTimeout()方法达到延迟执行某个方法的效果。还有一个的方法setInterval(),作用是每隔一段时间调用一次方法。两个方法都需要我们手动调用$apply()方法来触发$digest循环。
    ,AngularJS中有对应的$timeout$interval,不需要我们手动调用apply()方法触发digest循环。

    相关文章

      网友评论

          本文标题:AngularJs作用域高级特性,作用域属性监视、digest循

          本文链接:https://www.haomeiwen.com/subject/gwvckctx.html