问题
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 eventsEvents 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 therootScope
, 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