在Angular 1.x中交流组件或指令的有效方法 [英] Efficient way to communicate components or directives in Angular 1.x

查看:119
本文介绍了在Angular 1.x中交流组件或指令的有效方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据下图:

我想改善组件通信方法....我认为这种方法效率不高.

单击tabsetComponent发出事件时,父控制器将捕获此事件,从而更改rootScope变量.使用tableComponent中的$ watch rootScope变量来触发http提取数据功能...

有人可以用更好,更有效的方式来传达同级组件吗?

解决方案

用于组件之间通信的公认AngularJS方法是使用组件属性进行通信.

<div ng-controller="rootCtrl as vm">

    <tab-set-component tsc-click="vm.fn($event, data)">
    </tab-set-component>

    <table-component="vm.tableData">
    </table-component>

</div>

有关定义组件属性的更多信息,请参见 AngularJS综合指令API-隔离范围

最佳做法

仅将.$broadcast().$emit().$on()用于原子事件

与整个应用程序全局相关的事件(例如,用户身份验证或应用程序关闭).如果您想要特定于模块,服务或窗口小部件的事件,则应考虑使用服务,指令控制器或第三方库

  • $scope.$watch()应该代替对事件的需求
  • 直接注入服务和调用方法对于直接通信也很有用
  • 指令可以通过指令控制器直接相互通信

- AngularJS Wiki最佳实践


控制器示例

在您的html中,您使用的是来自根控制器的vm.fn,对吗?因此,您的建议是应调用click方法定义的根控制器,click方法将触发在rootScope上定义的http请求函数,然后获取表组件数据,然后将数据绑定到表组件属性上.

例如:

angular.module("myApp", []);

angular.module("myApp").controller("rootCtrl", function($http) {
    var vm = this;

    vm.tableData = { /* initial data */ };

    //click handler
    vm.fn = function(event, url) {
        $http.get(url).then (function onFulfilled(response) {
            vm.tableData = response.data;
        }).catch (function onRejected(response) {
            console.log(response.status);
        });
    };
});

以上示例避免了$rootScope混乱.所有业务逻辑和数据都包含在控制器中.

控制器为table-component设置初始数据,从tab-set-component接收点击事件,发出HTTP请求,处理错误,并将数据更新为table-component.


UPDATE-使用表达式绑定

另一种方法是使用表达式绑定来传递事件:

<header-component view="root.view" on-view-change="root.view = $event.view">
</header-component>

<main-component view="root.view"></main-component>

有关更多信息,请参见 SO:如何在不使用$ scope的同级组件之间传递数据,而不使用$ scope

在1.5.3版中,AngularJS在$compile服务中添加了$onChanges生命周期挂钩.

app.component("mainComponent",  {
      template: "<p>{{$ctrl.count}}",
      bindings: {view: '<'},
      controller: function() {
        this.count = 0;
        this.$onChanges = function(changesObj) {
            if (changesObj.view) {
                this.count++;
                console.log(changesObj.view.currentValue);
                console.log(changesObj.view.previousValue);
                console.log(changes)bj.view.isFirstChanged());
            };
        };    
      }
});

有关更多信息,请参见 AngularJS综合指令API参考-生命周期挂钩

另请参见 SO:AngularJs 1.5-组件不支持Watchers,如何解决?

According to the below image:

I want to improve components communication method....I think this way is not efficient.

When clicking tabsetComponent to emit event, then parent controller catch this event, changing rootScope variable. Using $watch rootScope variable in tableComponent to trigger http fetch data function...

Could anyone has better and efficient way to communicate sibling component?

解决方案

The accepted AngularJS method for communication between components is using component attributes for communication.

<div ng-controller="rootCtrl as vm">

    <tab-set-component tsc-click="vm.fn($event, data)">
    </tab-set-component>

    <table-component="vm.tableData">
    </table-component>

</div>

For more information on defining component attributes, see AngularJS Comprehensive Directive API -- isolate scope

Best practices

Only use .$broadcast(), .$emit() and .$on() for atomic events

Events that are relevant globally across the entire app (such as a user authenticating or the app closing). If you want events specific to modules, services or widgets you should consider Services, Directive Controllers, or 3rd Party Libs

  • $scope.$watch() should replace the need for events
  • Injecting services and calling methods directly is also useful for direct communication
  • Directives are able to directly communicate with each other through directive-controllers

-- AngularJS Wiki Best Practices


Controller Example

In your html, you use vm.fn that came from root controller right? So your advice is it should call the click method defined root controller, the click method will trigger http request function defined on the rootScope, then get table component datas, then bind the datas on table component attribute.

As example:

angular.module("myApp", []);

angular.module("myApp").controller("rootCtrl", function($http) {
    var vm = this;

    vm.tableData = { /* initial data */ };

    //click handler
    vm.fn = function(event, url) {
        $http.get(url).then (function onFulfilled(response) {
            vm.tableData = response.data;
        }).catch (function onRejected(response) {
            console.log(response.status);
        });
    };
});

The above example avoids cluttering $rootScope. All the business logic and data is contained in the controller.

The controller sets the initial data for the table-component, receives click events from the tab-set-component, makes HTTP requests, handles errors, and updates the data to the table-component.


UPDATE -- Using Expression Binding

Another approach is using expression binding to communicate events:

<header-component view="root.view" on-view-change="root.view = $event.view">
</header-component>

<main-component view="root.view"></main-component>

For more information, see SO: How to pass data between sibling components in angular, not using $scope

With version 1.5.3, AngularJS added the $onChanges life-cycle hook to the $compile service.

app.component("mainComponent",  {
      template: "<p>{{$ctrl.count}}",
      bindings: {view: '<'},
      controller: function() {
        this.count = 0;
        this.$onChanges = function(changesObj) {
            if (changesObj.view) {
                this.count++;
                console.log(changesObj.view.currentValue);
                console.log(changesObj.view.previousValue);
                console.log(changes)bj.view.isFirstChanged());
            };
        };    
      }
});

For more information, see AngularJS Comprehensive Directive API Reference -- Life-cycle hooks

See also SO: AngularJs 1.5 - Component does not support Watchers, what is the work around?

这篇关于在Angular 1.x中交流组件或指令的有效方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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