• angular $apply


    Javascript按轮次执行

    Javascript代码是按轮次执行的,从第一行开始一直到最后一行依次执行,正常情况下中间不会被中断,在代码执行的过程中浏览器不会有任何响应。
    不过任何异步回调,用户的输入操作等会新起一轮,新起的一轮会加入到事件轮询队列,直到下个CPU空闲会被执行。

    怎么实现双向数据

    一般来说有两种比较流行的方法:
    1.使用自定义的对象,这个对象的数据的更新需要用到自定义的set方法,而不是直接赋值。
    这样做的好处是,每次数据的更新我们都可以知道,接下来利用通知就可以更新DOM了。缺点是必须使用类似于
    obj.set('key', 'value')来设置属性的值,而不能直接用ojb.key='value'这种赋值方式。
    EmberJS和KnockoutJS用的就是这种实现方式。
    2.在每次执行轮次的结束阶段,检测变量的值是否发生了变化,然后再通知DOM进行更新。
    AngularJS用的就是第二种方式来实现双向数据绑定的。

    angular $apply and $digest

    在Angular里完成数据检测的工作是由$scope.$digest()来完成的,负责检测绑定的数据是否发生了变化。一般情况下我们不会直接用到这个函数,
    而是用$scope.$apply(),实际上$apply会帮我们调用$digest,只是他在外面包装了一层而已。

    $apply([exp]);
    $apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the angular framework we need to perform proper scope life cycle of exception handling, executing watches.

    
    Life cycle
    Pseudo-Code of $apply()
    function $apply(expr) {
      try {
        return $eval(expr);
      } catch (e) {
        $exceptionHandler(e);
      } finally {
        $root.$digest();
      }
    }
    
    

    Scope's $apply() method transitions through the following stages:
    The expression is executed using the $eval() method.
    Any exceptions from the execution of the expression are forwarded to the $exceptionHandler service.
    The watch listeners are fired immediately after the expression was executed using the $digest() method.
    Angular文档,$apply接收一个表达式字串,由$eval执行,并在执行后调用$digest方法。

    一般情况下我们很少会用到$apply函数,因为实际上所有的ng指令都帮我们包装了一层$apply,比如ng-click,$http。所以很少会显式去调用这个方法。
    而且在这些指令里面再调用会报错,在$apply函数里再次调用$apply会导致报错。

    如果现在有部分代码你需要在新的执行轮次运行,并且不是由Angular的内部库创建的,那么这种情况会需要用到$apply函数。这样在你的代码执行后,
    变量发生了改变就会被Angular检测到。

    比如下面这段代码:

    function Ctrl($scope) {
      $scope.message = "Waiting for update";
        
        setTimeout(function () {
            $scope.message = "Timeout called!";
            // AngularJS 不会意识到$scope发生了变化
        }, 2000);
    }
    

    回调函数里改变了$scope.message的值,但这不会被Angular检测到(因为根本没有进行检查)。
    所以我们需要手动调用$apply函数。

    
    //use $apply
    function testCtrl($scope) {
        $scope.message = 'hello world';
    
        setTimeout(function() { 
            $scope.$apply(function() {
                $scope.message = 'msg update';
            }); 
        }, 1000);
    }
    //ng $timeout 已经帮我们包装了$apply,所以一般情况下直接用$timeout就可以
    

    ng $watch

    每次在DOM增加一个变量就相当往ng 的$watch list 里增加一个$watch item
    每次end of turn都会检查$watch list的变量有没有变化

    //注册自己的$watch,并添加$digest时有变化的回调方法
    $scope.$watch('name', function(value) {
        
    });
    

    如果自己写的组件上更新了变量值,但没有调用$apply,那么就不会检测到该变量的变化。
    特别是某个地方用了$watch来检测某个值,然后这个值发生了改变,却没有执行变量值的检测,就会出现
    变量值发生了改变但是$watch却不会被调用的情况。

    这就很好地解释了为什么上次发生了这个事件: ``` $scope.setCity = function(item) { $scope.cityItem = item; $scope.blurCity(); }; //我却用$watch检测不到了 ```
  • 相关阅读:
    机器学习中的正则化问题(2)——理解正则化
    详解 Python 中的下划线命名规则
    编程面试的算法概念汇总
    group by多字段查询解决礼物统计
    一分钟学会Spring Boot多环境配置切换
    Maven 多模块父子工程 (含Spring Boot示例)
    第1章 Spring Cloud 构建微服务架构(一)服务注册与发现
    第3章 Spring Boot 入门指南
    第5章 Spring Boot 功能
    第4章 CentOS软件安装
  • 原文地址:https://www.cnblogs.com/hwencc/p/5813539.html
Copyright © 2020-2023  润新知