AngularJS $ onChanges为什么不注意到数组已更改?

时间:2019-01-01 15:49:50

标签: javascript angularjs

为什么没有角度通知数组已更改,但是如果我先将其更改为null呢?

我有一个AngularJS组件,该组件通过单向双向(=)数据绑定来接受数组。在父级中,我有一个按钮,其ng-click映射到此功能:

onClickAddValue()
{ 
    this.listOfValues.push(this.valueInput);
}

其中this.listOfValues是通过绑定传递给子组件的。此代码无效(子组件的视图未更新)。作为一个聪明的cookie,他事先完成了有关AngularJS的作业,我知道这是因为listOfValues的值没有改变,它仍然是相同的对象引用。所以我这样做:

onClickAddValue()
{ 
    var oldList = this.listOfValues;
    this.listOfValues = [];
    for (let value of oldList)
    {
        this.listOfValues.push(value);
    }
    this.listOfValues.push(this.valueInput);
}

但这也不起作用!我还尝试了Object.assignangular.copy。好像我的子组件根本没有注意到其输入的任何更改。但显然可以,因为下面的代码确实有效

onClickAddValue()
{ 
    var oldList = this.listOfValues;
    this.listOfValues = null;
    setTimeout(
        () =>
        {
            this.listOfValues = oldList;
            this.listOfValues.push(this.valueInput);
            this.$scope.$digest();
        }
    );  
}

这是怎么回事?我可以看到为什么最后一个代码段有效-listOfValues设置为null,ng-click自动触发摘要,角度通知新的null值,因此它更新视图,然后立即更新{{1 }}再次更改,另一个摘要被手动触发,视图再次更新。但是,为什么其他版本不起作用?为什么更改对象不同于将其更改为null,然后然后对其进行更改?

1 个答案:

答案 0 :(得分:1)

  

我正在监听对$onChanges中绑定的$onChanges的更改

使用Array.concat创建一个新对象, onClickAddValue() { this.listOfValues.push(this.valueInput); this.listOfValues = this.listOfValues.concat(); } 将检测到该对象:

$onChanges

Array.push Life-Cycle Hook仅检查引用的更改。它不检查内容更改。用Array.concat更改内容之后。使用angular.module("app",[]) .controller("ctrl", class { constructor () { this.listOfValues = [3,5]; } onClickAddValue() { this.listOfValues.push(this.valueInput); this.listOfValues = this.listOfValues.concat(); } }) .component("myComponent",{ bindings: {values: "<"}, template: ` <fieldset> {{$ctrl.values}}<br> changes={{$ctrl.changes}} </fieldset> `, controller: class { constructor () { this.changes=0; } $onChanges(ch) { this.changes++; //console.log(ch); } } })方法来创建一个新的对象,该对象将被变更检测器检测到。

The DEMO

<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl as $ctrl">
    <input ng-model="$ctrl.valueInput" /><br>
    <button ng-click="$ctrl.onClickAddValue()">Add value</button>
    <br>
    {{$ctrl.listOfValues}}
    <my-component values="$ctrl.listOfValues"></my-component>
</body>
listOfValues


更新

  

我做了很多工作,我认为这实际上与=是通过<绑定而不是<绑定绑定到子组件这一事实有关的-更改为$ngChanges绑定会使其突然起作用

'@'的文档清楚地说明了它具有属性('<')和单向($onChanges(changesObj))绑定的作用。

从文档中:

  

生命周期挂钩

     
      
  • <-每当单向(@)或插值(changesObj)绑定更新时调用。 { currentValue, previousValue, isFirstChange() }是一个哈希,其键是已更改的绑定属性的名称,值是"="形式的对象。使用此挂钩可触发组件内的更新,例如克隆绑定值以防止外部值的意外突变。请注意,初始化绑定时也会调用此方法。
  •   
     

AngularJS Comprehensive Directive API Reference - Life-Cycle Hooks

应避免双向({{1}})绑定,因为它增加了额外的监视程序,并且使向Angular 2+的迁移更加困难。

有关更多信息,请参见AngularJS Developer Guide - Component-based Application Architecture