mhe*_*ens 17 javascript angularjs angularjs-directive angularjs-scope
scope: { ... }在指令中使用会引入隔离范围,该范围不会从其父范围原型继承.但我总是将它用于不同的原因:使用双向数据绑定声明HTML属性的便捷方式:
scope: {
attr1: '=',
attr2: '?='
}
Run Code Online (Sandbox Code Playgroud)
要获得非隔离范围,必须使用scope: true,但不提供声明此类属性的机会.我现在发现自己需要一个具有非隔离范围的指令,但具有双向绑定.实现这一目标的最佳方法是什么?
示例:我的用例是这样的,在以下视图中outer-directive:
<div ng-repeat="e in element">
<inner-directive two-way-attr="e.value"></inner-directive>
</div>
Run Code Online (Sandbox Code Playgroud)
但是和inner-directive它在同一个模块中outer-directive.它不需要用隔离范围封装.实际上,我需要将$scope继承用于其他目的,因此隔离范围不是一种选择.只是使用HTML属性来建立这种双向通信非常方便.
mhe*_*ens 14
像素位的答案帮助我解决了这个问题,但是作为我原始问题的直接答案,它看起来过于复杂.在研究之后,解决方案非常简单.
使用如下隔离范围的指令:
scope: { model: '=myModel' },
link: function(scope, element, attr) {
//...
}
Run Code Online (Sandbox Code Playgroud)
以下是等效的,但范围不是隔离的:
scope: true,
link: function(scope, element, attr) {
scope.model = scope.$parent.$eval(attr.myModel);
//...
}
Run Code Online (Sandbox Code Playgroud)
在这里查看一个工作示例:http://jsfiddle.net/mhelvens/SZ55R/1/
在同一指令中可以同时具有非隔离范围和隔离范围.您可能希望这样做,例如,如果您混合使用两个非隔离模板(意味着它们不应通过范围继承查找绑定),以及隔离模板(它们应仅在其自己的范围内查找绑定)和它们都在同一个指令中定义.
要设置隔离范围和非隔离范围,您可以执行以下操作:
scope=true在链接函数中,根据scope参数编译和链接模板.执行此操作时,将针对非隔离范围评估绑定(意味着它通过原型范围继承解析绑定).
link: function(scope, element, attr) {
// this template should look for 'model' using scope inheritance
var template2 = angular.element('<div> Prototypical Scope: {{ model }}</div>');
// add the template to the DOM
element.append(template2);
// compile and link the template against the prototypical scope
$compile(template2)(scope);
}
Run Code Online (Sandbox Code Playgroud)
原型范围继承的优点是您不必将绑定显式导入指令的当前范围.只要它在当前作用域中定义,或者在继承链的更高位置(一直到根作用域)之前的任何作用域中定义,角度运行时将能够解析它.
在相同的链接功能中,使用定义隔离范围scope.$new(true).您可以通过将模型导入隔离范围来建立模型的双向绑定 - isolatedScope.model = scope.$eval(attr.model):
link: function(scope, element, attr) {
// this template should look for 'model' in the current isolated scope only
var template = angular.element('<div>Isolate Scope: {{model}}</div>');
// create an isolate scope
var isolatedScope = scope.$new(true);
// import the model from the parent scope into your isolated scope. This establishes the two-way binding.
isolatedScope.model = scope.$eval(attr.model);
// add the template to the DOM
element.append(template);
// compile and link the template against the isolate scope
$compile(template)(isolatedScope);
}
Run Code Online (Sandbox Code Playgroud)
隔离范围的优点是任何存在的绑定(即在范围内)都是您明确导入的绑定.将此与非隔离范围进行对比 - 其中绑定不需要在当前范围上明确定义 - 它可以从链上方的任何范围继承.
我写了这个.你这样使用它:
twowaybinder.attach($scope, $attrs.isDeactivated, 'isDeactivated');
.factory('twowaybinder', function ($parse) {
function twoWayBind($scope, remote, local){
var remoteSetter = $parse(remote).assign;
var localSetter = $parse(local).assign;
$scope.$parent.$watch(remote, function (value) {
localSetter($scope, value);
});
$scope.$watch(local, function (value) {
remoteSetter($scope, value);
});
}
return {
attach : twoWayBind
};
});
Run Code Online (Sandbox Code Playgroud)
它将从范围值给出真正的双向绑定.注意我不认为$ scope.$ parent是必要的,因为在继承或无范围的情况下,任何表达式都应解析当前范围.您只需要在隔离范围内调用$ parent,在这种情况下您不会使用它,您将使用隔离范围配置.