我最近一直在努力将我的指令(通常使用链接功能)切换为" web组件"通过将功能从链接功能移动到控制器(然后将其暴露给其他指令)。
我经常需要当前的组件。换句话说,如果组件A由B和C组成,它通常需要B和C的API,以便它可以起作用。 Angular不允许在DOM层次结构中需要下面的组件(我相信)。我发现自己使用了一个事件方案,在B和C激活之后,它们发出一个事件并将自己作为参数传递。然后,A处理这些事件,抓取B和C的引用,然后停止两个事件的传播。
考虑到这一点似乎落后了。对我来说,组件应该能够引用它所组成的组件。不应该将指令从下到上连接而不是自上而下?我的意思是,如果一个组件应该是一个自包含的黑盒子,它将API暴露给它周围的世界,那么它就不应该需要在它自身之外的组件。这破坏了组件之间的分离,似乎将它们结合起来。然而,要求内部的东西似乎是必须的......
基本上,我问两个问题: 1)除了#34之外,从外部(并且不需要从内部)要求的逻辑是什么;这就是Angular最初构建的方式"? 2)我正在使用的方案($指令激活事件)是一个好的方案还是有更好的方法从内部获取指令?
提前致谢。
答案 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