AngularJS-链接函数中的作用域被重置,我做错了什么

AngularJS - the scope is reset in the linking function, what am I doing wrong?

本文关键字:什么 错了 函数 链接 作用域 AngularJS-      更新时间:2023-09-26

我是AngularJS的初学者,我读过关于编译和链接的文章,但我仍然无法理解发生了什么。

我有这样的静态代码(类属性来自Bootstrap(:

<div ng-controller='AppCtrl'>
...
   <span class='input-group-addon'>{{typeOfCurrency}}</span>
...
   <ul class='nav nav-pills nav-stacked'>
      <li><a href='#', ng-click="typeOfCurrency = 'Bitcoin'">Bitcoin</a></li>
      <li><a href='#', ng-click="typeOfCurrency = 'Litecoin'">Litecoin</a></li>

当我点击链接时,正如预期的那样,它会将<span></span>中的typeOfCurrency设置为链接中的。

现在我有了另一个用ngRepeat动态创建的列表,我希望它在那里也能这样做:

...
   <span class='input-group-addon'>{{typeOfValue}}</span>
...
   <li ng-animate="'animate'" ng-repeat='currency in currencies | filter:search | limitTo:5'>
       <link-button></link-button>

然后我有一个用链接函数声明的指令:

app.directive('linkButton', function () {
    return {
        scope: true,
        restrict: "E",
        replace: true,
        template: "<a href=''>{{currency}}</a>",
        link: function (scope, elem, attrs) {
            elem.bind('click', function() {
                alert(scope.typeOfValue);
                scope.typeOfValue = scope.currency;
                alert(scope.typeOfValue);
            });
        }
    }
});

正如你所看到的,我在那里设置了2个警报。货币包含类似["USD"、"RON"、"ANG"、…、"GBP"]的内容。它创建了一个我可以点击的所有货币的列表。

当我遗憾地点击一个项目时,它不想更改"typeOfValue",我会发出警报,所以第一个警报说"美元",因为"typeOfValue"默认设置为美元,然后执行scope.typeOfValue = scope.currency;,第二个警报来了,说scope.typeOfValue现在是点击的货币,例如"RON"。但当我再次点击一个元素时,它再次告诉我"美元",而不是其他货币(例如"英镑"(。。。它不想更改<span></span>中的文本,也不想保存typeOfValue的新内容。

我做错了什么?我怎样才能做到这一点?

演示Plunker Here

这个问题与解析绑定时作用域继承的工作方式有关。您已经为指令创建了一个子作用域(指令中的scope=true(,这意味着将使用原型作用域继承来解析作用域变量。如果你不知道这意味着什么,概念很简单:如果在当前作用域上找不到作用域变量,它将在父作用域中查找绑定;如果它不在父作用域中,它将在grand-parent的作用域中查找绑定,等等,直到它找到作用域变量或没有找到,并停止在$rootScope。

作用域继承的工作方式是,如果您使用基元设置作用域变量,就像您在这里所做的那样:

scope.typeOfValue = scope.currency;

规则规定angular将在子作用域上创建变量的卷影副本,其名称与父作用域变量的名称相同。这有效地打破了模型绑定,因为现在有两个独立的模型,每个模型都在不同的范围内。

要解决此问题,请使用scope.obj.typeOfValue而不是scope.typeOfValue,并在父控制器中初始化obj:

 scope.obj = { typeOfValue: {} };

HTML:

<ul class='nav nav-pills nav-stacked'>
    <li><a href='#', ng-click="obj.typeOfCurrency = 'Bitcoin'">Bitcoin</a></li>
    <li><a href='#', ng-click="obj.typeOfCurrency = 'Litecoin'">Litecoin</a></li>

通过引入"."在模型中,angular将使用范围继承来查找模型(点的左侧(。一旦在父作用域中找到它,它将分配"typeOfValue"属性,该属性只是模型上的一个属性。这将保留绑定,以便当typeOfValue在子作用域中更改时,它会更新父作用域上的同一模型(反之亦然(。

[编辑]

该指令需要使用ng单击(而不是单击(,因为单击不会触发摘要循环。这是更新后的指令:

app.directive('linkButton', function () {
    return {
        scope: true,
        restrict: "E",
        replace: true,
        template: "<a href='#' ng-click='setCurrency(currency)'>{{currency}}</a>",
        link: function (scope, elem, attrs) {
            scope.setCurrency = function(currency) {
                //alert(scope.typeOfValue);
                scope.obj.typeOfValue = scope.currency;
                //alert(scope.typeOfValue);
            };
        }
    }
});