AngularJS:如何将常量对象绑定到指令

Mic*_*son 14 angularjs angularjs-directive angularjs-scope

我使用"scope"创建了一个带有绑定的指令.在某些情况下,我想绑定一个常量对象.例如,使用HTML:

<div ng-controller="Ctrl">
    <greeting person="{firstName: 'Bob', lastName: 'Jones'}"></greeting>
</div>
Run Code Online (Sandbox Code Playgroud)

和JavaScript:

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

app.controller("Ctrl", function($scope) {

});

app.directive("greeting", function () {
    return {
        restrict: "E",
        replace: true,
        scope: {
            person: "="
        },
        template:
        '<p>Hello {{person.firstName}} {{person.lastName}}</p>'
    };
});
Run Code Online (Sandbox Code Playgroud)

虽然这有效,但它也会导致JavaScript错误:

Error: 10 $digest() iterations reached. Aborting!
Run Code Online (Sandbox Code Playgroud)

(小提琴演示问题)

绑定常量对象而不导致错误的正确方法是什么?

Mic*_*son 11

这是我提出的解决方案,基于@ sh0ber的答案:

实现自定义link功能.如果属性是有效的JSON,那么它是一个常量值,所以我们只评估它一次.否则,请正常观察并更新值(换句话说,尝试表现为=绑定).scope需要设置为true确保指定的值仅影响该指令的实例.

(关于jsFiddle的例子)

HTML:

<div ng-controller="Ctrl">
    <greeting person='{"firstName": "Bob", "lastName": "Jones"}'></greeting>
    <greeting person="jim"></greeting>
</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

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

app.controller("Ctrl", function($scope) {
    $scope.jim = {firstName: 'Jim', lastName: "Bloggs"};
});

app.directive("greeting", function () {
    return {
        restrict: "E",
        replace: true,
        scope: true,
        link: function(scope, elements, attrs) {
            try {
                scope.person = JSON.parse(attrs.person);
            } catch (e) {
                scope.$watch(function() {
                    return scope.$parent.$eval(attrs.person);
                }, function(newValue, oldValue) {
                    scope.person = newValue;
                });
            }   
        },
        template: '<p>Hello {{person.firstName}} {{person.lastName}}</p>'
    };
});
Run Code Online (Sandbox Code Playgroud)


mar*_*cci 7

您收到该错误是因为Angular每次都在评估表达式.'='用于变量名称.

以下是两种在没有错误的情况下实现相同思考的替代方法.

第一解决方案

app.controller("Ctrl", function($scope) {
    $scope.person = {firstName: 'Bob', lastName: 'Jones'};
});

app.directive("greeting", function () {
    return {
        restrict: "E",
        replace: true,
        scope: {
            person: "="
        },
        template:
        '<p>Hello {{person.firstName}} {{person.lastName}}</p>'
    };
});

<greeting person="person"></greeting>
Run Code Online (Sandbox Code Playgroud)

二解决方案:

app.directive("greeting2", function () {
    return {
        restrict: "E",
        replace: true,
        scope: {
            firstName: "@",
            lastName: "@"
        },
        template:
        '<p>Hello {{firstName}} {{lastName}}</p>'
    };
});

<greeting2 first-name="Bob" last-Name="Jones"></greeting2>
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/7bNAd/82/