【问题标题】:One time binding: update model and re-render view一次性绑定:更新模型并重新渲染视图
【发布时间】:2015-07-07 14:14:51
【问题描述】:

我想知道是否可能,使用 Angular 一次性绑定,在模型更新后完全重新渲染视图/模板,也可以通过重新编译模板。 例如,在按下按钮时,可能是 react 的工作方式:我更新模型并明确强制更新视图。 基本上这是我想要实现的目标:

// controller
angular.module('app', []).controller('AppCtrl', function($scope) {
    $scope.items = [
        {id: 1},
        {id: 2},
        {id: 3}
    ];

    $scope.addAndRefresh = function() {
        $scope.items.push({id: 4});
        // manually call render logic here???
    };
});


<!-- HTML template -->
<div ng-repeat="item in ::items">
    {{item.id}}
</div>
<button ng-click="addAndRefresh()">Add</button>

通过单击“添加”按钮,我想刷新视图以查看新添加的项目。

【问题讨论】:

  • 为什么要完全重新渲染它,而不仅仅是依赖于修改数据的部分?
  • 我同样的问题:我有兴趣了解如何,如果可能的话,手动重新渲染一次性绑定模板,无论数据如何。
  • 恐怕 Stack Overflow 不是此类问题的论坛。在这里,您需要显示您尝试过的代码并解释您在做什么以及为什么这样做,以便人们可以帮助您。
  • Bizzarre:我一直认为 stackoverflow 是解决此类问题的正确位置。我有一个明显的问题(在我看来)我不知道如何处理。也许比我更聪明的人可以提供帮助!
  • @MatteoPiazza 检查我的回答,了解您的问题的几个解决方案。没有内置在 Angular 核心中,但在 Angular 2.0 之前,它可能与您所达到的一样接近。

标签: angularjs data-binding


【解决方案1】:

我也在想办法优雅地做到这一点。我希望框架中内置了一些东西来刷新一次性绑定。我想出的只是使用 ngIf 删除我想要刷新的元素并将其添加回来。

这是一个演示。单击“添加项目”按钮,您会看到由于重复的一次性绑定,列表不会刷新。检查刷新值并再次单击,项目将被更新:

var app = angular.module('demo', []);

app.controller('RefreshCtrl', function($scope, $timeout) {
  var counter = 4;

  $scope.visible = true;

  $scope.items = ['Item1', 'Item2', 'Item3'];

  $scope.addItem = function() {

    if ($scope.refresh) {
      $scope.visible = false;
    }

    $scope.items.push('Item' + counter);

    counter++;

    $timeout(function() {
      $scope.visible = true;
    });
  };

});
<script src="https://code.angularjs.org/1.3.17/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">

<div ng-app="demo" ng-controller="RefreshCtrl" class="container">
  <button class="btn btn-default" ng-click="addItem()">Add Item</button>
  <input type="checkbox" ng-model="refresh" />Refresh Values
  <div ng-if="visible">
    <h3 ng-repeat="item in ::items">{{item}}</h3>
  </div>

  <p>Items Array: {{items}}</p>
</div>

【讨论】:

  • 谢谢,这也是我在探索的一种方式,但和你一样,我也在寻找一种优雅的方式。
  • 感谢您的解决方案。有趣的是,它仅在您使用 Angular 的 $timeout 函数时才有效。使用原生 JS setTimeout() 函数(我最初尝试过)不起作用 - 然后视图无法识别 visible 更改。
  • @MathiasConradt 这是因为 setTimeout 没有开始新的摘要周期。循环遍历所有手表(包括 ng-if)并刷新/重新编译所有内容。
【解决方案2】:

根据您的需求,我会推荐以下两种解决方案之一:

我是前者的作者,它与其他解决方案的最大区别在于选择挂钩到$parse 服务。

因此,您可以在接受表达式的 Angular 的大多数 (如果不是全部) 区域中使用引入的 {{:refreshkey:expression}}/:refreshkey:expression 语法。


在您的情况下,实现可能如下所示:

js

angular.module('app', []).controller('AppCtrl', function($scope) {
  $scope.items = [
      {id: 1},
      {id: 2},
      {id: 3}
  ];

  $scope.addAndRefresh = function() {
      $scope.items.push({id: 4});
      /**
       * '$$rebind' is the internal namespace used by angular-bind-notifier.
       * 'refresh' is the refresh key used in your view.
       */
      $scope.$broadcast('$$rebind:refresh');
  };
});

标记

<!-- HTML template -->
<div ng-repeat="item in :refresh:items">
    {{::item.id}}
</div>
<button ng-click="addAndRefresh()">Add</button>

或者,如果你想要一些半动态的东西

js

angular.module('app', []).controller('AppCtrl', function($scope) {
  $scope.items = [
      {id: 1},
      {id: 2},
      {id: 3}
  ];

  $scope.add = function() {
      $scope.items.push({id: 4});
  };
});

标记

<!-- HTML template -->
<div bind-notifier="{ refresh: items.length }">
  <div ng-repeat="item in :refresh:items">
      {{::item.id}}
  </div>
</div>
<button ng-click="add()">Add</button>

查看READMEjsBin 了解一些用法示例。

【讨论】:

  • 小心 kcd 重新编译。我最近发现子组件范围在重新编译时不会被破坏。在长时间的会话和多次重新编译的过程中,这将使事情变得一团糟。 github.com/kentcdodds/kcd-angular/issues/8
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-18
  • 2011-09-05
  • 2023-03-13
相关资源
最近更新 更多