我一直在研究isolateScope指令,以便更好地了解它们如何与其他嵌套的isolateScope指令进行交互,因此将plnkr放在一起测试一些东西。
http://plnkr.co/edit/7Tl7GbWIovDSmVeKKN26?p=preview
这按预期工作。正如您所看到的,每个指令都有自己独立的模板。
然后我决定将每个指令中的html移动到主html文件中,但是它已停止工作了?我可以看到e1Ctrl
在指令的范围内,但在处理所附的标记时它似乎不可用。
http://plnkr.co/edit/33Zz1oO4q7BVFw0cMvYa?p=preview
有人可以告诉我为什么会这样吗?
-----------更新-----------
我已经简化了非工作人员以清楚地显示问题。该指令使用controllerAs
语法,e1Ctrl
明确设置$scope
(参见控制台输出)。
http://plnkr.co/edit/g2U2XskJDwWKuK3gqips?p=preview
angular
.module('app', [])
.controller('AppCtrl', AppCtrl)
.directive('elementOne', elementOne)
.controller('E1Ctrl', E1Ctrl)
function AppCtrl() {
var vm = this;
vm.data = [
{
label: 'one'
},
{
label: 'two'
},
{
label: 'three'
},
{
label: 'four'
}
];
vm.callback = function() {
console.log('called app callback');
};
}
function elementOne() {
return {
restrict: 'E',
scope: {
data: '=',
handler: '&'
},
controller: 'E1Ctrl',
controllerAs: 'e1Ctrl',
bindToController: true
}
}
function E1Ctrl($scope) {
console.log('E1Ctrl', $scope);
var vm = this;
vm.click = function() {
vm.handler();
};
vm.callback = function() {
console.log('called e1 callback');
};
}
标记:
<body ng-app="app" ng-controller="AppCtrl as appCtrl">
<ul>
<div ng-repeat='item in appCtrl.data'>
<element-one data='item' handler='appCtrl.callback()'>
<button ng-click='e1Ctrl.click()'>e1: {{e1Ctrl.data.label}}</button>
</element-one>
</div>
</ul>
</body>
------翻译解决方案-----
http://plnkr.co/edit/l3YvnKOYoNANteNXqRrA?p=preview
function elementOne() {
return {
restrict: 'E',
transclude: true,
scope: {
data: '=',
handler: '&'
},
controller: 'E1Ctrl',
link: function($scope, $element, $attr, ctrl, transclude) {
transclude($scope, function(clone){
$element.append(clone);
});
}
}
}
答案 0 :(得分:2)
指令的template
中的HTML范围与指令子树中的HTML的范围有所不同。前者是在指令范围内进行评估的;后者 - 在视图范围内。
如果指令具有隔离范围 - scope: {}
,则子树不会看到它。如果它使用scope: true
,那么它会为子树创建一个新的子范围,该子范围原型继承自View的范围。
请考虑以下事项:
// isolate scope
app.directive("foo", function(){
return {
scope: {},
link: function(scope){
scope.name = "foo";
}
}
});
// child scope
app.directive("bar", function(){
return {
scope: true,
link: function(scope){
scope.name = "bar";
}
}
});
app.controller("Main", function($scope){
$scope.name = "main";
});
以下是视图的呈现方式:
<body ng-controller="MainCtrl">
<pre>in main: {{name}} will render "main"</pre>
<foo>
<pre>in subtree of foo: {{name}} will render "main"</pre>
</foo>
<bar>
<pre>in subtree of bar: {{name}} will render "bar"</pre>
</bar>
</body>
在您的情况下,子树在View的范围内进行评估 - 而不是指令,这就是它无法按预期工作的原因。
修改强>
在某些情况下,在指令的隔离范围的上下文中评估子树是有意义的。我已经看到这与允许模板的指令一起使用。但要小心这一点,因为主视图的作者不应该(太多)知道指令的内部工作原理(即内部范围中暴露的内容)。这也很难阅读,因为你会看到在外部范围内没有意义的变量。
要评估指令的隔离范围中的子树,指令需要$compile
子树并将其与其范围相关联。
这是一个允许用户为列表中的每个项目提供模板的指令。 item
变量未在主范围中定义,仅在指令的隔离范围的上下文中有意义:
<list src="items">
<item-template>
{{item.a}} | {{item.b}}
</item-template>
</list>
指令'list'如下:
app.directive("list", function($compile){
return {
scope: {
src: "="
},
link: {
pre: function(scope, element){
var itemTemplate = element.find("item-template");
element.empty();
var template = angular.element('<div ng-repeat="item in src"></div>')
.append(itemTemplate.html());
element.append(template);
$compile(element.contents())(scope);
}
}
}
});