繁体   English   中英

AngularJS指令变异隔离范围数据

[英]AngularJS directive mutate isolate scope data

背景

我正在尝试使用2种方式的隔离范围属性来构建AngularJS指令。 该指令需要将数据突变为数组,以便能够使用ng-repeat正确显示它。 我知道从“ get”函数返回新数组时将发生无限摘要循环,因为这是一个新数组,AngularJS将继续考虑模型不稳定并继续进行摘要。

可以通过不使用“ get”函数返回新数组来解决此问题……但这对我来说不是一个选择,因为只要源数组发生更改,我就需要更改数组。 这是由隔离范围提供的功能,我不希望使用$scope.$watch()因为这将要求我注入$scope ,这是我试图通过使用bindToController: true摆脱的bindToController: true语法。

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

在Jsfiddle中: 链接 (请注意在打开开发人员工具控制台时出现无限摘要循环错误)

HTML:

<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>

Javascript(AngularJS版本:1.3.14):

angular.module('IsolateScopeExample', [])
    .controller('MainController', function(){
        this.dataToMutate = [{a: 1},{a: 2},{a: 3}];
    })
    .directive('mutator', function(){
        return {
            scope: {
                data: '=',
            },
            template: '<span ng-repeat="item in mvm.mutateData()">{{item}}</span>',
            bindToController: true,
            controller: function(){
                this.mutateData = function(){
                    console.log('Mutating');
                    var newData = [];
                    this.data.forEach(function(d){newData.push({b: d.a + 1});});
                    return newData;
                };
            },
            controllerAs: 'mvm'
        };
    });

不能完全确定为什么这样做,但这是我通常使用指令编写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);
        }
    };
});

@Joseph the Dreamer答案是正确的,但是如果您真的想摆脱$ scope并使用bindToController关于此的很棒的文章 ),则必须重用对同一数组的引用。

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

一个常见的错误是绑定到一个函数,该函数每次调用都会生成一个新数组。 例如:

<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;
            };
        },

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM