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

查看:25
本文介绍了在 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"></表格组件></div>

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

<块引用>

最佳做法

仅对原子事件使用 .$broadcast().$emit().$on()

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

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

-- AngularJS Wiki 最佳实践

<小时>

控制器示例

<块引用>

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

例如:

angular.module("myApp", []);angular.module("myApp").controller("rootCtrl", function($http) {var vm = 这个;vm.tableData = {/* 初始数据 */};//点击处理程序vm.fn = 函数(事件,网址){$http.get(url).then (function onFulfilled(response) {vm.tableData = response.data;}).catch (函数 onRejected(response) {console.log(response.status);});};});

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

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

<小时>

更新 -- 使用表达式绑定

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

<header-component view="root.view" on-view-change="root.view = $event.view"></标题组件><main-component view="root.view"></main-component>

有关更多信息,请参阅SO:如何在 Angular 中的兄弟组件之间传递数据,而不是使用 $scopep>

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

app.component("mainComponent", {模板:<p>{{$ctrl.count}}",绑定:{视图:'<'},控制器:函数(){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天全站免登陆