AngularJS指令变异隔离范围数据

时间:2015-08-25 20:07:14

标签: javascript angularjs angularjs-directive

背景

我尝试使用双向绑定隔离范围属性构建AngularJS指令。该指令需要将数据变更为数组,以便能够使用ng-repeat正确显示它。我知道当你从一个新的数组返回一个新的数组时会发生一个无限的摘要周期。因为它是一个新的数组而且AngularJS会继续考虑模型不稳定并继续消化。

这个问题可以通过不使用' get'来解决。函数返回一个新的数组...但这对我来说不是一个选项,因为每当源数组发生变化时我都需要改变变异数组。这是隔离范围提供的功能,我不想使用$scope.$watch(),因为这需要我注入$scope这是我试图通过使用{ {1}}语法。

问题

所以我的问题是,考虑到上面的背景:在AngularJS指令中改变隔离范围数据的正确方法是什么?

代码

在Jsfiddle中:link(注意打开开发人员工具控制台时无限的摘要周期错误)

HTML:

bindToController: true

Javascript(AngularJS版本:1.3.14):

<div ng-app="IsolateScopeExample" ng-controller="MainController as vm">
    <h4>Original data</h4>
    {{vm.dataToMutate}}
    <h4>Mutated data</h4>
    <div mutator data="vm.dataToMutate"></div>
</div>

2 个答案:

答案 0 :(得分:0)

不完全确定为什么会这样,但这就是我通常用指令编写Angular的方法。我看到的差异是我使用$scope。我将dataToMutate传递给指令。在指令的link中,我改变了dataToMutate。由于它是控制器中的相同对象,因此模板会相应更新。 https://jsfiddle.net/b7ekv4tm/2/

<强> HTML

<div ng-app="IsolateScopeExample" ng-controller="MainController">
    <h4>Original data</h4>
    {{dataToMutate}}
    <h4>Mutated data</h4>
    <div mutator data="dataToMutate"></div>
</div>

<强> JS

angular.module('IsolateScopeExample', [])
    .controller('MainController', ['$scope', function ($scope) {
    $scope.dataToMutate = [{
        a: 1
    }, {
        a: 2
    }, {
        a: 3
    }];
}])
    .directive('mutator', function () {
    return {
        scope: {
            data: '=',
        },
        template: '<span ng-repeat="item in data">{{item}}</span>',
        link: function ($scope) {
            var data = $scope.data.map(function (d) {
                return {
                    b: d.a + 1
                };
            });
            $scope.data = $scope.data.concat(data);
        }
    };
});

答案 1 :(得分:0)

@Joseph the Dreamer回答是正确的但是如果你真的想要摆脱$ scope并使用bindToController(顺便说一句。great article about this here)你将不得不重用对同一个数组的引用

实际上这正是文档所说的。错误链接指向的页面:

  

一个常见错误是绑定到每个&gt;生成新数组的函数。它被称为时间。例如:

<div ng-repeat="user in getUsers()">{{ user.name }}</div>
  

由于getUsers()返回新数组,因此Angular确定每个$ digest周期的模型不同,从而导致错误。如果元素没有改变,解决方案是返回相同的数组对象

var users = [ { name: 'Hank' }, { name: 'Francisco' } ];

$scope.getUsers = function() {
  return users;
};

所以你的洗礼就是这样的:

controller: function(){
            var mutated = [];
            this.mutateData = function(){
                console.log('Mutating');
                var newData = [];
                this.data.forEach(function(d){newData.push({b: d.a + 1});});
                mutated.length = 0;
                mutated.push.apply(newData, mutated);
                return mutated;
            };
        },