上面的JSFiddle是为解释这个问题而设立的。但是,基本上:
HTML:
<breadcrumb></breadcrumb>
<div ng-view></div>
Angular Directive&amp;路由:
angular
.module('app', [])
.directive('breadcrumb', function() {
return {
restrict: 'E',
template: "<ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul>",
replace: true,
controller: Ctrl1
}
})
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
template: '<h1>{{pgTitle}}</h1>',
controller: Ctrl2
});
}]);
控制器
function Ctrl1($scope) {
$scope.path = [{
label: 'Home',
url: '#/'}];
$scope.pgTitle = "Home"
}
function Ctrl2($scope, $routeParams) {
$scope.path = [{
label: 'Home',
url: '#/'},{
label: 'Node 2',
url: '#/node2'}];
$scope.pgTitle = "Node 2"
}
我期待在Ctrl2中更改$scope.path
将更新breadcrumb指令,但它没有发生。我不得不相信它与它们的相对范围有关,但根本不能理解它看得怎么样。我已经阅读了很多文章和StackOverflow帖子,但没有什么特别的东西可以让我看到我错过的内容。
我希望有人能指出我正确的方向。
非常感谢!
nz的
答案 0 :(得分:5)
你的小提琴不工作的原因是因为(正如你正确识别的)范围问题。您的Ctrl1
是控制器,用于控制指令的范围。该指令正在寻找一个名为path
的变量,它是一个路径数组。如果我们看一下该范围内的路径变量,它似乎只包含1个值。
function Ctrl1($scope) {
$scope.path = [{
label: 'Home',
url: '#/'}];
$scope.pgTitle = "Home"
}
现在您希望在另一个控制器path
中更改此变量Ctrl2
。我假设您试图让Ctrl2
“的范围继承Ctrl1
的范围。要实现此目的,请首先检查定义了哪个元素Ctrl2
。该元素(html元素)是Ctrl1
元素的子元素吗?
来自您的HTML:
Ctrl1
的元素:<breadcrumb></breadcrumb>
Ctrl2
的元素:<div ng-view></div>
要让Ctrl2
成为Ctrl1
的孩子:您的HTML结构应如下所示:
<breadcrumb>
<div ng-view></div>
</breadcrumb>
如果我们对您的代码进行此更改,它仍然无法正常工作。这是因为当angular查看<breadcrumb>
的指令时,它不知道它应该对该节点内部的东西做什么。 <breadcrumb>
是一个html节点。由于它是一个节点,因此它可以包含其中的内容/其他节点。当您使用模板替换此痕迹导航节点时,您还应该给出效果的角度指示:“如果您发现我的内容,请将其放在此处”。这就是你如何做到的。
将指令代码修改为:
.directive('breadcrumb', function() {
return {
restrict: 'E',
template: "<div><ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul><div ng-transclude></div></div>",
replace: true,
transclude : true,
controller: Ctrl1
}
})
这里几乎没有差异/变化。
现在您将注意到内容现在已被替换。除了路径没有使用子控制器的路径值更新。看看这个https://stackoverflow.com/a/14049482/1057639答案。这是对范围/原型继承的惊人解释。基本上,您对路径的写入是在子范围中创建一个新的路径变量,该路径变量掩盖了父路径(指令正在使用该路径)。
在这种情况下,最好的办法是在父作用域中创建一个addPath函数,并在定义新的子视图时使用它(在子作用域中)添加新的Path。
这是完成所有这些工作的fiddle。