我遵循本书的指令,并决定在只读范围上尝试他们的代码。但是,我得到了奇怪的结果。
应该发生的事情是:
我还注意到,摆弄角度版本降至1.1.1解决了这个问题。虽然我接受一些小的版本更改可能会影响整体行为,但我不明白为什么,例如,案例3停止工作或为什么在案例1中标题仍然读取原始应用程序标题(" Hello World" )值而不是作用域标题只读值(" Hello World指令")。有人可以解释一下吗?
以下是代码:
HTML
<div ng-app="demoApp">
<div ng-controller="AppController">
<div ng-init="title = 'Hello World'">
<h2 id="appTitle">{{ title }}</h2>
<button id="newAppTitle" ng-click="setAppTitle('App 2.0')">Upgrade Me!</button>
<div my-scoped-directive="" msd-title="Directive of {{ title }}">
<h4 id="directiveTitle">{{ title }}</h4>
<button id="newDirTitle" ng-click="setDirectiveTitle('bob')">Bob it!</button>
</div>
</div>
</div>
</div>
JS
var demoApp = angular.module('demoApp', []);
demoApp.controller("AppController", function($scope) {
$scope.setAppTitle = function(t) {
$scope.title = t;
};
});
demoApp.directive("myScopedDirective", function() {
return {
scope: {
title: '@msdTitle'
},
link: function(scope, element, attrs) {
scope.setDirectiveTitle = function(t) {
scope.title = t;
};
}
};
});
的jsfiddle
答案 0 :(得分:1)
这本书可能已经过时(可能是基于早期版本的Angular)。
有两件事是错的:
1。无法从HTML访问myScopeDirective隔离范围内的'setDirectiveTitle':
<div my-scoped-directive="" msd-title="Directive of {{ title }}">
<!--*** THE CONTENTS BELOW THE DIRECTIVE ARE BOUND TO AppController's SCOPE ***-->
<h4 id="directiveTitle">{{ title }}</h4>
<button id="newDirTitle" ng-click="setDirectiveTitle('bob')">Bob it!</button>
</div>
setDirectiveTitle('bob')绑定到AppController的范围而不是指令的隔离范围。在AppController的范围内,该方法不存在。由于隔离范围是“隔离的”并且不从父(AppController的范围)继承范围,因此按钮单击实际上不会执行任何操作。
<强> 2 即可。指令下的内容绑定到AppController的范围 - 而不是孤立的范围。所以'title'模型实际上与它上面的'appTitle'模型相同。两个标题都说“Hello World”的原因是因为它们都与AppController范围内的同一模型“标题”绑定。这也是为什么当单击第一个按钮时,两个标题同时更改为同一标题的原因。
我认为作者犯的主要错误是myScopedDirective下的内容绑定到隔离范围的错误假设。对于早期版本的Angluar,这可能是正确的,但对于Angular 1.2及更高版本肯定不是这样。内容绑定到父作用域(AppController的作用域)。
答案 1 :(得分:1)
在Angular中使用范围有时会让人感到困惑。还需要记住的是,“链接”功能与控制器不同,这就是使用控制器创建指令的原因。如果您在指令中需要自定义功能,则可以使用JQLite绑定内容(不推荐),也可以为指令创建控制器。这确实要求您还使用指令所需的HTML模板(这可以使用模板内联,或者使用templateUrl解压缩到html)。这是您的指令的更新示例(代码后的更多解释)
demoApp.directive("myScopedDirective", function() {
return {
template: '<h4 id="directiveTitle">Directive of {{ directiveTitle }}</h4><button id="newDirTitle" ng-click="setDirectiveTitle(\'bob\')">Bob it!</button>',
scope: {
title: '=msdTitle',
directiveTitle: '@msdTitle'
},
controller: function($scope){
$scope.setDirectiveTitle = function(t) {
$scope.directiveTitle = t;
};
},
link: function(scope, element, attrs) {
scope.$watch('title', function(){
scope.directiveTitle = scope.title;
});
}
};
});
由于您的要求是当父控制器范围内的标题发生变化时,指令标题也应该更改,我们基本上需要复制标题,但如您所见,我使用@
作为标题标题为directiveTitle
和=
。 @将取标题的初始值,但不会观察属性的变化,而每当指定的属性发生变化时,=都会发生变化,在本例中为AppController.title
。
在我们的链接功能中,我们现在在原始标题上设置了$watch
,以确保我们能够在AppController.title
更改时保持最新状态。
setDirectiveTitle
现在是注入指令控制器的作用域的函数,并更改directiveTitle
属性,该属性再次绑定在我们的模板中。
不确定这是否正是您想要的,但它似乎符合您的要求。 :)
更新了小提琴: