无法在 Angular 隔离范围指令上调用方法
Unable to call method on Angular isolate-scope directive
鉴于以下示例,我很好奇为什么 scope:true
会按预期方式切换元素。但是,如果使用 scope:{}
,则 ng-click
不会调用 toggle 方法。通过我自己的实验,是否使用bindToController和controllerAs并没有什么区别,问题是一样的。
(function(angular) {
'use strict';
angular.module('test', [])
.directive('collapsibleMenu', [function() {
return {
scope: {}, // doesn't work
//scope: true, // works
restrict: 'A',
controller: function() {
var ctrl = this;
ctrl.open = false;
ctrl.toggle = function() {
ctrl.open = !ctrl.open;
console.log('toggle', ctrl.open);
}
},
bindToController: true,
controllerAs: 'ctrl'
};
}]);
})(window.angular);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<div ng-app="test">
<div collapsible-menu>
<button ng-click="ctrl.toggle()">toggle menu 0</button>
<ul role="menu" ng-show="ctrl.open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
<div collapsible-menu>
<button ng-click="ctrl.toggle()">toggle menu 1</button>
<ul role="menu" ng-show="ctrl.open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
</div>
我不是指令和作用域继承方面的专家,但让我印象深刻的是你的指令并不是真正的指令:它没有 link 函数,并且代码包含在标签确实应该在模板中。
指令标签内代码的重复证明指令是完全无用的:您也可以直接在 HTML 本身中声明控制器。
它被称为 isolat(ed) 是有原因的。隔离作用域中的 ctrl
与 <button ng-click="ctrl.toggle()">
中的 ctrl
不同。
我猜误解源于你认为<div collapsible-menu>
的内容就是指令的内容,其实不是。 collapsible-menu
与页面其余部分完全 "isolated"(原文如此!)。
你可以这样使用
HTML:
<div ng-app="test">
<div collapsible-menu>
<button ng-click="toggle()">toggle menu 0</button>
<ul role="menu" ng-show="open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
<div collapsible-menu>
<button ng-click="toggle()">toggle menu 1</button>
<ul role="menu" ng-show="open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
</div>
JS:
angular.module("test", []).
directive("collapsibleMenu", function () {
return {
restrict: "A",
transclude: true,
scope: {},
link: function (scope, element, attrs, ctrl, transclude) {
transclude(scope, function (clone) {
element.append(clone);
});
scope.open = false;
scope.toggle = function () {
scope.open = !scope.open;
console.log('toggle', scope.open);
};
}
};
});
鉴于以下示例,我很好奇为什么 scope:true
会按预期方式切换元素。但是,如果使用 scope:{}
,则 ng-click
不会调用 toggle 方法。通过我自己的实验,是否使用bindToController和controllerAs并没有什么区别,问题是一样的。
(function(angular) {
'use strict';
angular.module('test', [])
.directive('collapsibleMenu', [function() {
return {
scope: {}, // doesn't work
//scope: true, // works
restrict: 'A',
controller: function() {
var ctrl = this;
ctrl.open = false;
ctrl.toggle = function() {
ctrl.open = !ctrl.open;
console.log('toggle', ctrl.open);
}
},
bindToController: true,
controllerAs: 'ctrl'
};
}]);
})(window.angular);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<div ng-app="test">
<div collapsible-menu>
<button ng-click="ctrl.toggle()">toggle menu 0</button>
<ul role="menu" ng-show="ctrl.open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
<div collapsible-menu>
<button ng-click="ctrl.toggle()">toggle menu 1</button>
<ul role="menu" ng-show="ctrl.open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
</div>
我不是指令和作用域继承方面的专家,但让我印象深刻的是你的指令并不是真正的指令:它没有 link 函数,并且代码包含在标签确实应该在模板中。 指令标签内代码的重复证明指令是完全无用的:您也可以直接在 HTML 本身中声明控制器。
它被称为 isolat(ed) 是有原因的。隔离作用域中的 ctrl
与 <button ng-click="ctrl.toggle()">
中的 ctrl
不同。
我猜误解源于你认为<div collapsible-menu>
的内容就是指令的内容,其实不是。 collapsible-menu
与页面其余部分完全 "isolated"(原文如此!)。
你可以这样使用
HTML:
<div ng-app="test">
<div collapsible-menu>
<button ng-click="toggle()">toggle menu 0</button>
<ul role="menu" ng-show="open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
<div collapsible-menu>
<button ng-click="toggle()">toggle menu 1</button>
<ul role="menu" ng-show="open" class="ng-cloak">
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
<li><a href="#">link</a></li>
</ul>
</div>
</div>
JS:
angular.module("test", []).
directive("collapsibleMenu", function () {
return {
restrict: "A",
transclude: true,
scope: {},
link: function (scope, element, attrs, ctrl, transclude) {
transclude(scope, function (clone) {
element.append(clone);
});
scope.open = false;
scope.toggle = function () {
scope.open = !scope.open;
console.log('toggle', scope.open);
};
}
};
});