如何从更新的父项列表更新子组件

时间:2017-04-08 17:04:16

标签: angularjs angular-components

我是Angular的新手,目前正在使用1.6版本。

我正在实现Angular的组件样式。我只是想问一下从父组件到子组件进行通信的最佳方式是什么?我知道有一个问题,但我有一个特定的场景(我不确定它是否独特)。

以下是该方案:

模态 - >创建新的待办事项 - >父(更新对象) - >个人待办事项(更新名单)

  1. 我有一个用于创建待办事项的模式。
  2. 然后在创建新的待办事项后,传递父项上的值以更新待办事项的对象。
  3. 当我将todo传递的父列表更新为个人待办事项组件以更新视图上的列表时。
  4.   angular.module('tab')
        .controller('TabController', TabController);
    
      function TabController() {
        let vm = this;
        let updatedTodoObject = {};
    
        vm.$onInit = function () {
          vm.personalTodo = vm.todo.own_todo;
          vm.externalTodo = vm.todo.external_todo;
        }
    
        vm.$onChanges = function (changes) {
          console.log('I\'m triggered');
        }
    
        vm.updateTodoList  = updateTodoList;
    
       function updateTodoList( result ) {
        updatedTodoObject = angular.copy(vm.todo);
        updatedProjectObject.user_todos.push(result)
        if( vm.todo !== updatedTodoObject) {
         vm.todo = updatedTodoObject;
        } else {
         console.log("Still in reference");
        }
       }
    
        vm.getUpdatedTodotList = function( ) {
          return vm.todo;
        }
      }
    
       
    angular.module('...')
        .component('...', {
          bindings: {
            onResultTodoUpdated: '&'
          },
          controllerAs: 'todo',
          controller: ['TodoService', '$log', '$state', function(TodoService, $log, $state) {
            let vm = this;
            let todo = {};
    
            vm.newTodoModal = function() {
              TodoService.newTodoModal()
                .then(function (TodoName) {
                  TodoService.createTodo(TodoName)
                    .then(function(response) {
                      if( response.status === 201 ) {
    
                        todo = {
                          ...
                          ...
                        }
    
                        vm.onResultTodoUpdated( { result: todo } );
                      }
                    })
                    .catch(function(error) {
                      console.log(error);
                    });
    
      angular.module('...')
        .component('...', {
          bindings: {
            todos: "<"
          },
          controllerAs: 'personal',
          controller: function(){
            let vm = this;
            vm.isShowTodoArchived = false;
    
            vm.$onInit = function () {
              getWatchedTodo();
            }
    
            function getWatchedTodo () {
             vm.todos = vm.todos;
             vm.todosSize = vm.todos.length;
            }
    

    我的问题是我在创建负责显示待办事项列表的子组件后如何传递更新的数据?

    已更新

    <div class="tab-pane active" id="todosTab">
      <nv-new-todo on-result-todo-updated="todo.updateTodoList(result)"></nv-new-project>
    
      <div class="my-todos">
        <nv-personal-todo todos="todo.personalTodo" ></nv-personal-todo>
        <nv-external-todo todos="todo.externalTodo"></nv-external-todo>
      </div>
    </div>
    

1 个答案:

答案 0 :(得分:8)

如何使用父项更改来更新子组件

使用one-way bindings <

  
      
  • <<attr - 在本地范围属性和通过属性attr传递的表达式之间建立单向(单向)绑定。表达式在父作用域的上下文中计算。如果未指定attr名称,则假定属性名称与本地名称相同。您还可以通过添加?<?<?attr来使绑定成为可选项。
  •   
     

例如,给定<my-component my-attr="parentModel">scope: { localModel:'<myAttr' }的指令定义,则隔离范围属性localModel将反映父范围上parentModel的值。对parentModel的任何更改都会反映在localModel中,但localModel中的更改不会反映在parentModel中。

     

- AngularJS Comprehensive Directive API Reference - scope

$onChanges生命周期挂钩:

  
      
  • $onChanges(changesObj) - 每当更新单向绑定时调用。 changesObj是一个哈希,其键是已更改的绑定属性的名称,值是{ currentValue, previousValue, isFirstChange() }形式的对象。使用此挂钩来触发组件内的更新。
  •   
     

- AngularJS Developer Guide - Components

使用对象内容 - 使用$doCheck生命周期挂钩

绑定对象或数组引用时,$onChanges挂钩仅在引用的更改时执行。要检查对象或数组的内容的更改,请使用$doCheck生命周期挂钩:

app.component('nvPersonalTodo', {
  bindings: {
    todos: "<"
  },
  controller: function(){
    var vm = this;
    this.$doCheck = function () {
      var oldTodos;
      if (!angular.equals(oldTodos, vm.todos)) {
        oldTodos = angular.copy(vm.todos);
        console.log("new content");          
        //more code here
      };
    }
})

来自文档:

  

控制器可以提供以下充当生命周期钩子的方法:

     
      
  • $doCheck() - 在摘要周期的每个回合调用。提供检测和处理更改的机会。必须从此挂钩调用您希望采取的任何响应您检测到的更改的操作;实现这一点对于调用$onChanges时没有影响。例如,如果您希望执行深度相等检查,或检查Date对象,Angular的更改检测器无法检测到的更改,则此挂钩可能非常有用>因此不会触发$onChanges。这个钩子在没有参数的情况下被调用;如果检测到更改,则必须将以前的值进行比较与当前值。
  •   
     

- AngularJS Comprehensive Directive API Reference -- Life-cycle hooks

欲了解更多信息,

简单DEMO

&#13;
&#13;
angular.module("app",[])
.component("parentComponent", {
    template: `
        <fieldset>
            Inside parent component<br>
            parentData={{$ctrl.parentData}}
            <child-component in-data="$ctrl.parentData"></child-component>
        </fieldset>
    `,
    controller: function () {
        this.$onInit = () => {
            this.parentData = 'test'
        };
    },
})
.component("childComponent",{
    bindings: {
        inData: '<',
    },
    template: `
        <fieldset>Inside child component<br>
            inData={{$ctrl.inData}}
        </fieldset>
    `,
})
&#13;
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
    <parent-component>
    </parent-component>
<body>
&#13;
&#13;
&#13;

有关详细信息,请参阅