Angular的指令作为Web组件 - 为什么需要?

时间:2016-01-31 01:13:17

标签: javascript angularjs

我最近一直在努力将我的指令(通常使用链接功能)切换为" web组件"通过将功能从链接功能移动到控制器(然后将其暴露给其他指令)。

我经常需要当前的组件。换句话说,如果组件A由B和C组成,它通常需要B和C的API,以便它可以起作用。 Angular不允许在DOM层次结构中需要下面的组件(我相信)。我发现自己使用了一个事件方案,在B和C激活之后,它们发出一个事件并将自己作为参数传递。然后,A处理这些事件,抓取B和C的引用,然后停止两个事件的传播。

考虑到这一点似乎落后了。对我来说,组件应该能够引用它所组成的组件。不应该将指令从下到上连接而不是自上而下?我的意思是,如果一个组件应该是一个自包含的黑盒子,它将API暴露给它周围的世界,那么它就不应该需要在它自身之外的组件。这破坏了组件之间的分离,似乎将它们结合起来。然而,要求内部的东西似乎是必须的.​​.....

基本上,我问两个问题: 1)除了#34之外,从外部(并且不需要从内部)要求的逻辑是什么;这就是Angular最初构建的方式"? 2)我正在使用的方案($指令激活事件)是一个好的方案还是有更好的方法从内部获取指令?

提前致谢。

1 个答案:

答案 0 :(得分:0)

您的代码示例违反了encapsulation

的原则
  

示例违反了封装原则

angular.module('app').controller('coolTextBoxCtrl', coolTextBoxCtrl)
function coolTextBoxCtrl($scope) {
    var vm = this;

    vm.enabled = true;
    vm.model = '';

    activate();

    function activate() {
        console.log('publishing $scope');
        $scope.$emit('coolTextBoxActivated', vm);
    }
}

通过将隔离范围发布到要使用的世界,此示例违反了encapsulation,这是面向对象编程的四个基本原则之一。封装使用来隐藏类中的结构化数据对象的值或状态,从而防止未经授权的人员使用。直接访问它们。 1

更好的方法是使用bind-to-controller

angular.module('app').directive('coolTextBox', coolTextBox)
function coolTextBox() {
    return {
        restrict: 'E',
        controller: 'coolTextBoxCtrl as ctbc',
        template: '<input ng-model="ctbc.model">'+
                  '<p ng-style="{\'font-weight\': '+
                        'ctbc.enabled?\'bold\':\'\'}">'+
                  'scope-{{$id}}</p>'+
                  '{{ctbc}}'+
                  '<hr>',
        scope: {
            model: '=cbtModel',
            enabled: '=enabled'
        },
        bindToController: true
    }
}

然后使用属性公开公共变量。

    <cool-text-box
       enabled="cfc.ctbc.enabled"
       cbt-model="cfc.ctbc.model"
    ></cool-text-box>

有关bindToController的详情,请参阅AngularJS $compile Service Reference -- Comprehensive Directive API

Updated DEMO on PLNKR