如何从更新的父组件列表中更新子组件 [英] How to update child components from the updated list of parents

查看:28
本文介绍了如何从更新的父组件列表中更新子组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Angular 的新手,目前使用的是 1.6 版.

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

场景如下:

Modal -> 创建新的 todo -> Parent(更新对象)-> 个人 todo(更新列表)

  1. 我有一个用于创建待办事项的模式.
  2. 然后在创建新的 todo 之后传递父级的值来更新 todo 的对象.
  3. 当我将待办事项的父列表更新到个人待办事项组件以更新视图上的列表时.

 angular.module('tab').controller('TabController', TabController);功能 TabController() {让 vm = 这个;让 updatedTodoObject = {};vm.$onInit = 函数 () {vm.personalTodo = vm.todo.own_todo;vm.externalTodo = vm.todo.external_todo;}vm.$onChanges = 函数(变化){console.log('我被触发了');}vm.updateTodoList = updateTodoList;函数 updateTodoList( 结果 ) {更新的TodoObject = angular.copy(vm.todo);更新的ProjectObject.user_todos.push(result)if( vm.todo !== updatedTodoObject) {vm.todo = updatedTodoObject;} 别的 {console.log("仍在参考中");}}vm.getUpdatedTodotList = function() {返回 vm.todo;}}

angular.module('...').成分('...', {绑定:{onResultTodoUpdated: '&'},controllerAs: 'todo',控制器:['TodoService','$log','$state',函数(TodoService,$log,$state){让 vm = 这个;让待办事项 = {};vm.newTodoModal = 函数(){TodoService.newTodoModal().then(function (TodoName) {TodoService.createTodo(TodoName).then(功能(响应){如果(响应.状态=== 201){待办事项 = {......}vm.onResultTodoUpdated( { result: todo } );}}).catch(函数(错误){控制台日志(错误);});

 angular.module('...').成分('...', {绑定:{待办事项:<"},controllerAs: '个人',控制器:函数(){让 vm = 这个;vm.isShowTodoArchived = false;vm.$onInit = 函数 () {getWatchedTodo();}函数 getWatchedTodo() {vm.todos = vm.todos;vm.todosSize = vm.todos.length;}

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

更新

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

解决方案

如何使用父组件的更改更新子组件

使用单向绑定<

<块引用>
  • < - 在局部范围属性和通过属性 属性.该表达式是在父作用域的上下文中计算的.如果未指定属性名称,则假定属性名称与本地名称相同.您还可以通过添加 ? 使绑定成为可选的:<?.

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

AngularJS 综合指令 API 参考 - 范围

还有 $onChanges 生命周期钩子:

<块引用>
  • $onChanges(changesObj) - 每当更新单向绑定时调用.changesObj 是一个散列,其键是已更改的绑定属性的名称,值是 { currentValue, previousValue, isFirstChange() } 形式的对象.使用此钩子触发组件内的更新.

AngularJS 开发者指南 - 组件


使用对象内容——使用$doCheck生命周期钩子

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

app.component('nvPersonalTodo', {绑定:{待办事项:<"},控制器:函数(){var vm = 这个;this.$doCheck = 函数 () {var oldTodos;如果 (!angular.equals(oldTodos, vm.todos)) {oldTodos = angular.copy(vm.todos);console.log(新内容");//更多代码在这里};}})

来自文档:

<块引用>

控制器可以提供以下方法作为生命周期钩子:

  • $doCheck() - 在摘要循环的每一轮调用.提供了检测变化并采取行动的机会.您希望为响应您检测到的更改而采取的任何操作都必须从此挂钩调用;实现这一点对 $onChanges 何时被调用没有影响.例如,如果您希望执行深度相等性检查,或者检查日期对象,Angular 的更改检测器不会检测到其更改并且因此不会触发,则此钩子可能很有用$onChanges. 这个钩子是不带参数调用的;如果检测到变化,您必须存储以前的值以与当前值进行比较.

——AngularJS综合指令API参考——生命周期钩子

欲了解更多信息,


简单的演示

angular.module("app",[]).component("父组件", {模板:`<字段集>在父组件内部<br>parentData={{$ctrl.parentData}}<child-component in-data="$ctrl.parentData"></child-component></fieldset>`,控制器:函数(){this.$onInit = () =>{this.parentData = '测试'};},}).component("子组件",{绑定:{输入数据:'<',},模板:`<fieldset>子组件内部<br>inData={{$ctrl.inData}}</fieldset>`,})

<script src="//unpkg.com/angular/angular.js"></script><body ng-app="app"><父组件></父组件>

有关详细信息,请参阅

I'm new to Angular and currently using version 1.6.

I'm implementing the component style of Angular. I just want to ask what's the best way to communicate from parent to child components? I know there is an existing question but I have a specific scenario (I'm not sure if it's unique or not).

Here is the scenario:

Modal -> create new todo -> Parent ( update the object ) -> personal todo ( update the list )

  1. I have a modal for creating todo.
  2. Then after creating new todo pass the value on the parent to update the object of todo.
  3. And when I updated the parent list of todo pass to the personal todo components to update the list on the view.

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

My question again is how I can pass the updated data after I create to the child component which is in charge of displaying the todo list?

UPDATED

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

解决方案

How to update child components with changes from parents

Use one-way bindings <

  • < or <attr - set up a one-way (one-directional) binding between a local scope property and an expression passed via the attribute attr. The expression is evaluated in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. You can also make the binding optional by adding ?: <? or <?attr.

For example, given <my-component my-attr="parentModel"> and directive definition of scope: { localModel:'<myAttr' }, then the isolated scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel, but changes in localModel will not reflect in parentModel.

AngularJS Comprehensive Directive API Reference - scope

And the $onChanges life-cycle hook:

  • $onChanges(changesObj) - Called whenever one-way bindings are updated. The changesObj is a hash whose keys are the names of the bound properties that have changed, and the values are an object of the form { currentValue, previousValue, isFirstChange() }. Use this hook to trigger updates within a component.

AngularJS Developer Guide - Components


With object content — Use the $doCheck Life-cycle Hook

When binding an object or array reference, the $onChanges hook only executes when the value of the reference changes. To check for changes to the contents of the object or array, use the $doCheck life-cycle hook:

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

From the Docs:

The controller can provide the following methods that act as life-cycle hooks:

  • $doCheck() - Called on each turn of the digest cycle. Provides an opportunity to detect and act on changes. Any actions that you wish to take in response to the changes that you detect must be invoked from this hook; implementing this has no effect on when $onChanges is called. For example, this hook could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not be detected by Angular's change detector and thus not trigger $onChanges. This hook is invoked with no arguments; if detecting changes, you must store the previous value(s) for comparison to the current values.

AngularJS Comprehensive Directive API Reference -- Life-cycle hooks

For more information,


Simple DEMO

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>
    `,
})

<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
    <parent-component>
    </parent-component>
<body>

For more information, see

这篇关于如何从更新的父组件列表中更新子组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆