在AngularJS组件中将事件从父级传递给子级 [英] Communicating Events from Parent to Child in AngularJS Components

查看:92
本文介绍了在AngularJS组件中将事件从父级传递给子级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我正在开发的新项目中,我已经开始使用组件而不是指令。

in the new project I'm working on I've started using the components instead of directives.

然而,我遇到了一个我找不到的问题这是一个具体的标准方法。

however, I've encountered an issue where I cannot find a concrete standard way to do it.

从孩子到父母的事件很容易通知,你可以在我的plunkr上找到它,但是通知的正确方法是什么从父母到孩子的事件?

It's easy to notify an event from child to parent, you can find it on my plunkr below, but what's the correct way to notify a event from parent to child?

Angular2似乎通过使用类似的东西来解决这个问题: https://angular.io/docs/ts/latest/cookbook/component-communication.html #!#parent-to-child-local-var
但我不认为定义子组件的指针是可能的,就像#timer

Angular2 seems to solve this issue by using something like this: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child-local-var But I don't tink there's a possibilty to define a "pointer" to the child component like the example did with #timer

为了保证可能轻松转换为Angular2,我想避免:

In order to mantain a possible easy conversion to Angular2 I want to avoid:


  • 事件发生(从范围发出和广播)

  • 使用来自子项的require(然后添加一个回调给parent..UGLY)

  • 使用单向绑定,将范围注入孩子,然后看这个属性..更多UGLY

示例代码:

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

app.controller('RootController', function() {
});

app.component('parentComponent', {
  template: `
    <h3>Parent component</h3>
    <a class="btn btn-default btn-sm" ng-click="$ctrl.click()">Notify Child</a>
    <span data-ng-bind="$ctrl.childMessage"></span>
    <child-component on-change="$ctrl.notifiedFromChild(count)"></child-component>
  `,
  controller: function() {
    var ctrl = this;
    ctrl.notifiedFromChild = function(count){
      ctrl.childMessage = "From child " + count;
    }
    ctrl.click = function(){
    }
  },
  bindings: {
  }
});

app.component('childComponent', {
  template: `
    <h4>Child component</h4>
    <a class="btn btn-default btn-sm" ng-click="$ctrl.click()">Notify Parent</a>
  `,
  controller: function() {
    var ctrl = this;
    ctrl.counter = 0;
    ctrl.click = function(){
        ctrl.onChange({ count: ++ctrl.counter });
    }
  },
  bindings: {
    onChange: '&'
  }
});

你可以在这里找到一个例子:

You can find an example here:

http://plnkr.co/edit/SCK8XlYoYCRceCP7q2Rn?p=preview

这是我创建的可能解决方案

This is a possible solution I created

http://plnkr.co/edit/OfANmt4zLyPG2SZyVNLr?p=preview

孩子需要父,然后子设置父子的父引用...现在父母可以使用孩子...丑陋,但它就像上面的angular2示例

where the child requires the parent, and then child sets a parent reference to the child... now parent can use the child... ugly but it's like angular2 example above

推荐答案

在AngularJS组件中将事件从父级传递给子级



使用表达式绑定发布指令$ API



要允许父组件将事件传递给子组件,让子组件发布API:

Communicating Events from Parent to Child in AngularJS Components

Publish Directive $API Using Expression Binding

To allow parent components to communicate events to a child component, have the child publish an API:

<grid-component grid-on-init="$ctrl.gridApi=$API; $ctrl.someFn($API)">
</grid-component>    

JS

app.component('gridComponent', {
  //Create API binding
  bindings: {gridOnInit: "&"},
  template: `
    <h4>Grid component</h4>
    <p> Save count = {{$ctrl.count}}</p>
  `,
  controller: function() {
    var ctrl = this;
    this.$onInit = function() {
        ctrl.count = 0;
        ctrl.api = {};
        //Publish save function
        ctrl.api.save = save;
        //Invoke Expression with $API as local
        ctrl.gridOnInit({$API: ctrl.api});
    };
    function save(){
      console.log("saved!");
      ctrl.count++;
    }
  }
});

上面的例子调用 grid-on-init定义的Angular Expression 属性,其API公开为 $ API 。这种方法的优点是父级可以通过使用Angular Expression将函数传递给子组件来对子初始化做出反应。

The above example invokes the Angular Expression defined by the grid-on-init attribute with its API exposed as $API. The advantage to this approach is that the parent can react to child initialization by passing a function to the child component with the Angular Expression.

来自文档:


'isolate'范围对象哈希定义了一组从指令元素的属性派生的局部范围属性。这些本地属性对于模板的别名值很有用。对象哈希中的键映射到隔离范围上的属性名称;这些值通过匹配指令元素上的属性来定义属性如何绑定到父作用域:

The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the directive's element. These local properties are useful for aliasing values for templates. The keys in the object hash map to the name of the property on the isolate scope; the values define how the property is bound to the parent scope, via matching attributes on the directive's element:


  • & ; & attr - 提供了在父作用域的上下文中执行表达式的方法。如果未指定attr名称,则假定属性名称与本地名称相同。给定< my-component my-attr =count = count + value> 和隔离范围定义范围: {localFn:'& ; myAttr'} ,隔离范围属性 localFn 将指向 count = count + value表达式的函数包装器。通常需要通过表达式将数据从隔离范围传递到父范围。这可以通过将局部变量名称和值的映射传递到表达式包装器fn来完成。例如,如果表达式是 increment($ amount),那么我们可以通过调用 localFn 来指定金额值 localFn({$ amount:22})

  • & or &attr - provides a way to execute an expression 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. Given <my-component my-attr="count = count + value"> and the isolate scope definition scope: { localFn:'&myAttr' }, the isolate scope property localFn will point to a function wrapper for the count = count + value expression. Often it's desirable to pass data from the isolated scope via an expression to the parent scope. This can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment($amount) then we can specify the amount value by calling the localFn as localFn({$amount: 22}).

- AngularJS综合指令API - 范围

作为惯例,我建议在 $ 前加上局部变量,以区别于父变量。

As a convention, I recommend prefixing local variables with $ to distinguish them from parent variables.

注意:为了简化向Angular 2+的过渡,请避免使用双向 = 绑定。而是使用单向< 绑定和表达式& 绑定。有关详细信息,请参阅 AngularJS开发人员指南 - 了解组件

NOTE: To ease the transition to Angular 2+, avoid the use of bi-directional = binding. Instead use one-way < binding and expression & binding. For more information, see AngularJS Developer Guide - Understanding Components.

要允许父组件将事件传递给子组件,请让子组件发布API:

To allow parent components to communicate events to a child component, have the child publish an API:

<grid-component api="$ctrl.gridApi"></grid-component>

在上面的例子中, grid-component 使用绑定将其API发布到父作用域上,使用 api 属性。

In the above example, the grid-component uses bindings to publish its API onto the parent scope using the api attribute.

app.component('gridComponent', {
  //Create API binding
  bindings: {api: "="},
  template: `
    <h4>Grid component</h4>
    <p> Save count = {{$ctrl.count}}</p>
  `,
  controller: function() {
    var ctrl = this;
    this.$onInit = function() {
        ctrl.count = 0;
        ctrl.api = {};
        //Publish save function
        ctrl.api.save = save;
    };
    function save(){
      console.log("saved!");
      ctrl.count++;
    }
  }
});

然后父组件可以调用子 save 使用已发布API的函数:

Then the parent component can invoke the child save function using the published API:

ctrl.click = function(){
  console.log("Search clicked");
  ctrl.gridApi.save();
}

PLNKR上的DEMO

这篇关于在AngularJS组件中将事件从父级传递给子级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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