【问题标题】:Efficient way to communicate components or directives in Angular 1.x在 Angular 1.x 中通信组件或指令的有效方式
【发布时间】:2016-06-02 06:23:50
【问题描述】:

根据下图:

我想改进组件通信方式....我认为这种方式效率不高。

当点击 tabsetComponent 发出事件时,父控制器会捕捉到这个事件,改变 rootScope 变量。使用tableComponent中的$watch rootScope变量触发http获取数据函数...

谁能有更好更有效的方式来交流兄弟组件?

【问题讨论】:

    标签: angularjs angularjs-directive components watch


    【解决方案1】:

    公认的组件间通信的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 Comprehensive Directive API -- isolate scope

    最佳做法

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

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

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

    -- AngularJS Wiki Best Practices


    控制器示例

    在您的 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。


    更新 -- 使用表达式绑定

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

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

    欲了解更多信息,请参阅SO: How to pass data between sibling components in angular, not using $scope

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

    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 Comprehensive Directive API Reference -- Life-cycle hooks

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

    【讨论】:

    • 在您的 html 中,您使用来自根控制器的 vm.fn 对吗?所以你的建议是它应该调用根控制器上定义的click方法,click方法将触发rootScope上定义的http请求函数,然后获取表组件数据,然后绑定表组件属性上的数据。你认为在根控制器中定义 http fetch 函数效率更高吗?而且通过这些方式,我们不需要使用任何事件方法,对吗?
    • 查看添加的控制器示例
    • 感谢您的详细解释:) 另一个问题,如果根范围内有很多组件,我们将在根控制器中定义很多功能,是正确的方法吗?根控制器会太重而无法高效执行?
    • 上面的控制器示例没有使用$rootScope。它使用$rootScope 的子作用域。您可以通过将{{'scope-id'=+$id}} 放入其模板中来检查。 $rootScope 的 ID 为 1。子作用域的数字从 1 递增。
    • 对不起,我打错字了...其实我想说的是,如果我在根控制器中定义了很多根控制器中的组件需要的功能,那么根控制器会不会太重?
    猜你喜欢
    • 1970-01-01
    • 2017-07-12
    • 2016-11-10
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 2018-01-04
    • 2016-09-11
    相关资源
    最近更新 更多