我是否在角度指令之外正确地共享状态?(父作用域/$rootScope问题)



我的页面上有两个元素,它们没有以某种方式嵌套。对于第一个属性,我想设置第二个属性的内容,如下所示:

<body>
<input info="This is some info"></input>
<div>{{info}}</div>
</body>

我知道可以像"AngularJS-属性指令输入值更改"中所描述的那样做类似的事情,但在我的情况下,属性的内容是模型值。此外,我已经在使用ng-model来处理输入的值。

最后我解决了这样的问题:

<body>
<input infobox info="This is some info"></input>
<div>{{info}}</div>
</body>
app.directive('infobox', function() {
return {
restrict : 'A',
scope : {
info : '@info'
},
controller: function($rootScope, $scope) {
$rootScope.info = $scope.info;
}
};
});

jsfiddle

因此,我通过直接转到$rootScope来绕过任何孤立的作用域传递值,但这感觉像是一种逃避。本质上,我不知道链上可能有什么控制器或作用域,因为我需要能够在任何地方使用这个组件。

另一种解决方案是为整个页面设置一个父控制器,但这只是一个伪根作用域。另一个更麻烦的解决方案是有两个指令或控制器,并使用几乎像总线一样的事件进行通信。它会起作用,但我们不要那样做。

有"干净"的方法吗?

/edit

这里有一个应该工作的干净解决方案(在jsfiddle中确实如此):

<body>
<div info="this is some info"></div>
<div>{{info}}</div>
</body>
app.directive('info', function() {
return {
restrict : 'A',
link: function(scope, element, attrs, ngModel) {
scope.info = attrs.info;
}
};
});

jsfiddle。

然而,在我的现实生活场景中,价值被卡在了链条的某个地方。是否可能是一个具有隔离作用域的父指令一直在阻止级联?

/edit2

这是一个我认为肯定会奏效的解决方案。它涉及三个指令,其中一个是其他两个的父母。评论中建议的解决方案组合:

jsfiddle

然而,在我自己的代码中,它仍然不起作用。尽管看起来很简单,但infoManager.info仍然是undefined

我最近在类似的情况下使用了另一种方法(我也会恢复到"rootscope越狱"one_answers"事件发射/监听"模式来解决其他问题),这可能对你有用:假设我们有这个指令:

app.directive('infobox', function() {
return {
restrict : 'A',
scope : {
info : '@info'
},
controller: function($rootScope, $scope) {
//$rootScope.info = $scope.info;
this.setInfo = function(data){
$scope.info = data;
}
this.getInfo = function(){
return $scope.info;
}
}
};
})

现在我可以添加另一个显示{{info}}:的指令

使用html:

app.directive('showinfo', function(){
return {
restrict:'A',
template:'<div>{{info}}</div>',
require:'^infobox', //this is where the magic happens
link:function(scope,element,attrs,parentCtrl){ //notice that now er have a "parentctrl, with everything that is on 'this' in the required direcive
//you can set a watch for this etc..
scope.info = parentCtrl.getInfo();
}
}
})

希望这能有所帮助!

编写第三个指令,它可以作为需要了解变量的范围的标记,也可以作为范围的替代。无论哪种方式,都需要第三个指令位于{{info}}infobox之上,并且需要位于底部的两个指令将其作为父指令。

好吧,我终于拿到了。上一次编辑关闭了它,但我读的是控制器的信息,而不是控制器的作用域。

解决方案如下:

<body>
<div infomanager>
<div info="'this is some info'"></div>
<div showinfo></div>
</div>
</body>
var app = angular.module('app', []);
app.directive('infomanager', function() {
return {
controller: function($scope) {
this.scope = $scope;
}
};
});
app.directive('info', function() {
return {
restrict : 'A',
require: '^infomanager',
scope : {
info : '=info'
},
link: function(scope, element, attrs, infoManager) {
infoManager.scope.info = scope.info;
}
};
})
app.directive('showinfo', function(){
return {
template:'{{info}}',
require:'^infomanager'
}
})

jsfiddle

这里有一个更好的例子来证明这一点:jsfiddle

最新更新