javascript - 强制刷新 Angular 中的嵌套函数

标签 javascript angularjs arrays

我是 Angular(1.x) 的完全初学者,我一直在尝试将其整合到我当前正在开发的应用程序中。

它基本上通过 ajax(多个嵌套数组)接收整个用户数据,然后使用嵌套的 ng-repeat 指令继续渲染它们。在最里面的重复中,我运行一个函数,该函数根据当前日期返回数据。

<div ng-repeat="i in rootArray">
  <div ng-repeat="h in i.array1">
    <div ng-repeat="j in h.array2">
      <span>{{dateBasedFunction(j.data)}}</span>
    </div>
  </div>
</div>

函数中的数据随着时间的推移而变化(即使输入保持不变),我希望它重新运行以反射(reflect)这些变化,而无需再次渲染整个结构。

这可能吗?我不确定我是否遵循了最佳框架的实践,也许有更好的方法?

谢谢!

最佳答案

背景

ng-repeats 不会造成任何问题。我们需要关注interpolation expression :{{dateBasedFunction(j.data)}}

Angular 正在创建一个 watcherdigest 的每次迭代中对表达式 dateBasedFunction(j.data) 进行脏检查循环。如果自上次摘要以来结果值已更改,则 DOM 将使用新值进行更新。

问题是,您的代码中没有任何内容触发 Angular 摘要周期。

工作示例

在这里,我们可以通过用户交互手动触发摘要来查看您的情况:

var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope', MyCtrl]);

function MyCtrl($scope) {
  
  $scope.rootArray = [{
    "array1": [{
      "array2": [{
        "data": "hello"
      }, {
        "data": "world"
      }]
    }]
  }];

  //Dummy $watch alerts whenever digest is called
  $scope.$watch(function() {
    console.log('Digest called');
  });

  $scope.dateBasedFunction = function(x) {
    var d = new Date();
    return x + ' (' + d.getMinutes() + ":" + d.getSeconds() + ")";
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="MyCtrl">
  
  <button ng-click="">ng-click calls digest()</button>
  
    <div ng-repeat="i in rootArray">
      <div ng-repeat="h in i.array1">
        <div ng-repeat="j in h.array2">
          <span>{{dateBasedFunction(j.data)}}</span>
        </div>
      </div>
    </div>
    
  </div>
</div>

每次单击按钮时,ng-click 都会触发 Angular 摘要。这会重新评估dateBasedFunction。由于值已更改,因此 DOM 会重新绘制。

但是,我假设您不想依赖 ng-click 来保持 DOM 更新。您希望 DOM 定期更新,因为它会根据当前日期/时间而变化。

可能的解决方案

  1. 确定适合您需求的频率,并定期强制执行摘要周期:

var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope', MyCtrl]);

function MyCtrl($scope) {
  
  $scope.rootArray = [{
    "array1": [{
      "array2": [{
        "data": "hello"
      }, {
        "data": "world"
      }]
    }]
  }];

  //Dummy $watch alerts whenever digest is called
  $scope.$watch(function() {
    console.log('Digest called');
  });

  $scope.dateBasedFunction = function(x) {
    var d = new Date();
    return x + ' (' + d.getMinutes() + ":" + d.getSeconds() + ")";
  }
  
  //Call $scope.$apply() every second.
  setInterval(function() {
    //$scope.$apply() triggers a digest cycle
    $scope.$apply();
  }, 1000);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="MyCtrl">
  
    <div ng-repeat="i in rootArray">
      <div ng-repeat="h in i.array1">
        <div ng-repeat="j in h.array2">
          <span>{{dateBasedFunction(j.data)}}</span>
        </div>
      </div>
    </div>
    
  </div>
</div>

  • 如果您知道更新的频率,您可以考虑编写一个在正确时间直接更新 DOM 的指令,而无需在整个范围内调用 apply() 。这会更高效,但需要更多的开发工作。

    这正是angular-moment与他们的 am-time-ago directive 一起做。该指令具有类似的目标:更新响应当前日期/时间而变化的数据。

  • 使用 Angular 观察模型的任何更改,但在 Angular 之外处理基于日期/时间的更改:

  • var myApp = angular.module('myApp', []);
    myApp.controller('MyCtrl', ['$scope', MyCtrl]);
    
    function MyCtrl($scope) {
    
      $scope.rootArray = [{
        "array1": [{
          "array2": [{
            "data": "hello"
          }, {
            "data": "world"
          }]
        }]
      }];
    
      //Dummy $watch alerts whenever digest is called
      $scope.$watch(function() {
        console.log('Digest called');
      });
    }
    
    function dateBasedFunction(x) {
      var d = new Date();
      return x + ' (' + d.getMinutes() + ":" + d.getSeconds() + ")";
    }
    
    setInterval(function() {
      $('[data-date-based-value]').each(function() {
        this.textContent = dateBasedFunction(this.dataset['dateBasedValue']);
      });
    }, 1000);
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    
    <div ng-app="myApp">
      <div ng-controller="MyCtrl">
    
        <div ng-repeat="i in rootArray">
          <div ng-repeat="h in i.array1">
            <div ng-repeat="j in h.array2">
            
              <!--Set a data-date-based-value attribute-->
              <!--Angular will keep the attribute value updated-->
              <!--But the element's text will be updated via jQuery-->
              <span ng-attr-data-date-based-value="{{j.data}}"></span>
              
            </div>
          </div>
        </div>
    
      </div>
    </div>

    请注意,此解决方案直接更新 DOM,无需运行额外的摘要周期。

    This article如果您有兴趣了解有关 Angular 的更多信息,它很好地解释了摘要周期。

    关于javascript - 强制刷新 Angular 中的嵌套函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45322961/

    相关文章:

    javascript - 根据单选按钮选择设置隐藏输入值

    javascript - 在 AngularJS 中,哪些模块可以覆盖常量?

    c - 指向字符串的指针数组(指针的基本类型)

    arrays - typescript 类型检查不适用于数组过滤器

    AngularJS : UI-router WARNING: Tried to load angular more than once

    c - 使用 int 数组作为 switch case

    javascript - 转换 .each() 因为它很慢

    javascript - 数组到对象的数组 - javascript

    javascript - AngularJS orderBy 过滤器不适用于货币

    angularjs - 如何定义注入(inject)动态组件的位置?