Efficient way to communicate components or directives in Angular 1.x

被刻印的时光 ゝ 提交于 2019-12-05 02:44:53

问题


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?


回答1:


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?



来源:https://stackoverflow.com/questions/35526318/efficient-way-to-communicate-components-or-directives-in-angular-1-x

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!