【问题标题】:How to avoid digest cycle delay from two-way binding如何避免双向绑定造成的消化循环延迟
【发布时间】:2019-08-24 18:06:57
【问题描述】:

Angularjs 何时触发双向数据绑定?

在 AngularJS 应用程序中,我有一个父指令和一个子指令。

父指令

angular
  .module('myApp')
  .directive('customForm', function(customService, apiV1, Constants, $timeout) {
    return {
      restrict: 'E',
      scope: {
        param1: '=',
        param2: '=?',
        boolean1: '@?'
      },
      template,
      link: function(scope, parentController) {
      scope.data = customService.newClient;
      //some stuff...

childDirective JS:

angular
  .module('myApp')
  .directive('customToolForm', function () {
    return {
      restrict: 'E',
      scope: {
        name: '=',
        city: '=',
        postalCode: '='
      },
      template,
      controller: function ($scope, $rootScope, Constants, apiV1, customService) {

     $scope.doSomethingWithPostalCode = function() {
         $scope.$parent.doSomethingWithPostalCode();
     }
     //some stuff...

parentDirective HTML 片段:

<address-client-creation name="data.client.name" city="data.client.city"
                         postal-code="data.client.postalCode">
</address-client-creation>

childDirective HTML 片段:

 <input maxlength="5" type="text" data-ng-model="postalCode"
        data-ng-change="doSomethingWithPostalCode();">

我的问题是:

从childDirective触发doSomethingWithPostalCode方法时,child中的postalCode的值与parent的client.postalCode不一样,而是在方法的末尾。

看来更新父值的双向绑定事件是在函数调用之后发生的

所以我的问题是在调用方法之前确保 $parent 范围更新的最佳方法是什么?

【问题讨论】:

    标签: html angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    如何避免双向绑定导致的消化循环延迟

    AngularJS 框架通过向子作用域添加一个观察者来实现双向 ('=') 绑定,该观察者将数据从子作用域传输到父作用域。观察者需要一个摘要循环来检测变化并进行传输。

    一种更现代的方法是对输入使用单向 ("&lt;") 绑定,对输出使用表达式 ("&amp;") 绑定:

    app.directive('customToolForm', function () {
        return {
          restrict: 'E',
          scope: {
            name: '<',
            city: '<',
            ̶p̶o̶s̶t̶a̶l̶C̶o̶d̶e̶:̶ ̶'̶=̶'̶
            postalCode: '<',
            postalCodeChange: '&',
          },
          template: `
              <input maxlength="5" type="text" data-ng-model="postalCode"
                     data-ng-change="doSomethingWithPostalCode(postalCode);">
          `,
          controller: function ($scope, $rootScope, Constants, apiV1, customService) {
    
         $scope.doSomethingWithPostalCode = function(postalCode) {
             ̶$̶s̶c̶o̶p̶e̶.̶$̶p̶a̶r̶e̶n̶t̶.̶d̶o̶S̶o̶m̶e̶t̶h̶i̶n̶g̶W̶i̶t̶h̶P̶o̶s̶t̶a̶l̶C̶o̶d̶e̶(̶)̶;̶
             $scope.postalCodeChange({$event: postalCode});
         }
         //some stuff...
    

    用法:

    <custom-form-tool 
        name="data.client.name" city="data.client.city"
        postal-code="data.client.postalCode"
        postal-code-change="data.client.postalCode=$event; doSomething($event)"
    >
    </custom-form-tool>
    

    使用表达式 ("&amp;") 绑定立即使事件数据可用于父控制器。

    它还使迁移到 Angular 2+ 的路径更容易。

    有关详细信息,请参阅

    【讨论】:

    • 好的,谢谢,很清楚。与此同时,我找到了一个“解决方案”,使用 $scope.$watch(postalCode) 似乎首先更新了绑定。您认为这是一个足够好的解决方案吗? @georgeawg
    • 发布您的解决方案,我会告诉您我的想法。见Can I answer my own question?
    【解决方案2】:

    我发现的一个解决方案是在 childDirective 中使用$watch

        /**
         * Using $watch instead of data-ng-change ensure that bindings are updated
         */
        $scope.$watch('postalCode', function() {
           $scope.$parent.doSomethingWithPostalCode();
        });
    

    然后在子指令的输入中删除the data-ng-change

     <input maxlength="5" type="text" data-ng-model="postalCode">
    

    在 $watch 方法中调试时,我可以验证父 $scope 是否已经更新。

    不确定它是真正的解决方案还是更像是 hack。

    【讨论】:

    • 使用$scope.$parentcode smell,这是更深层次问题的征兆。在这种情况下,它将组件硬连接到父控制器中的特定方法。使用表达式 ("&amp;") 绑定允许组件的用户绑定到父控制器中的任何方法。 $scope.$watch 在 Angular 2+ 应用程序中也不可用。这将使迁移到 Angular 2+ 变得更加困难。
    猜你喜欢
    • 2020-09-03
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    相关资源
    最近更新 更多