Javascript 如何在没有隔离作用域的指令*中获得双向数据绑定?
在指令中使用Javascript 如何在没有隔离作用域的指令*中获得双向数据绑定?,javascript,angularjs,angularjs-directive,angularjs-scope,Javascript,Angularjs,Angularjs Directive,Angularjs Scope,在指令中使用scope:{…}将引入一个隔离作用域,它通常不会从其父作用域继承。但我总是出于不同的原因使用它:通过双向数据绑定方便地声明HTML属性: scope: { attr1: '=', attr2: '?=' } 要获得非隔离作用域,必须使用scope:true,这不提供声明此类属性的机会。我现在发现自己需要一个具有非隔离作用域但具有双向绑定的指令。实现这一目标的最佳方式是什么 示例:在外部指令的视图中,我的用例是这样的: <div ng-repeat="e i
scope:{…}
将引入一个隔离作用域,它通常不会从其父作用域继承。但我总是出于不同的原因使用它:通过双向数据绑定方便地声明HTML属性:
scope: {
attr1: '=',
attr2: '?='
}
要获得非隔离作用域,必须使用scope:true
,这不提供声明此类属性的机会。我现在发现自己需要一个具有非隔离作用域但具有双向绑定的指令。实现这一目标的最佳方式是什么
示例:在
外部指令的视图中,我的用例是这样的:
<div ng-repeat="e in element">
<inner-directive two-way-attr="e.value"></inner-directive>
</div>
但是内部指令
与外部指令
位于同一模块中。它不需要用隔离作用域封装。事实上,我需要将$scope
继承用于其他目的,因此隔离作用域不是一个选项。只是使用HTML属性建立这种双向通信非常方便。
在相同的指令中可以同时具有非隔离作用域和隔离作用域。例如,如果您混合了非隔离模板(这意味着它们不应该通过作用域继承查找绑定)和隔离模板(它们应该只在自己的作用域中查找绑定),并且它们都是在同一个指令中定义的,那么您可能希望这样做
要同时设置隔离作用域和非隔离作用域,可以执行以下操作:
在指令定义中,指定scope=true
在link函数中,根据scope参数编译并链接模板。执行此操作时,将根据非隔离作用域对绑定求值(这意味着它通过原型作用域继承解析绑定)
隔离作用域的优点是,存在的任何绑定(即在作用域中的绑定)都是显式导入的绑定。与非隔离作用域相比,绑定不需要在当前作用域上显式定义,它可以从链上更高的任何作用域继承
pixelbits的答案帮我解决了这个问题,但作为对我最初问题的直接回答,它似乎过于复杂了。仔细研究之后,解决方案真的很简单
采用具有如下隔离范围的指令:
scope: { model: '=myModel' },
link: function(scope, element, attr) {
//...
}
以下内容是等效的,但范围不是孤立的:
scope: true,
link: function(scope, element, attr) {
scope.model = scope.$parent.$eval(attr.myModel);
//...
}
请参见此处的工作示例:我写了这个。您可以这样使用它:
scope: { model: '=myModel' },
link: function(scope, element, attr) {
//...
}
twowaybinder.attach($scope,$attrs.isDeactivated,'isDeactivated')代码>
它将从范围值提供真正的双向绑定。注意,我不认为$scope.$parent是必需的,因为在继承或无作用域场景中,任何表达式都应该在当前作用域上解析。您只需要在隔离作用域中调用$parent,在这种情况下,您不需要使用它,而是使用隔离作用域配置 您可以使用两个指令
如果gg是一个对象,那么“=”指向一个内存位置
angular.module('mymodule', []).directive('a', function($parse, $modal) {
return {
restrict : 'A',
scope : {
gg : "="
},
require : "b",
link : function(scope, element, attrs, bCtrl) {
scope.$watch('gg',function(gg){
bCtrl.setset(scope.gg);
}
}
}
});
angular.module('mymodule').directive('b', function($parse, $modal) {
return {
restrict : 'A',
/*
* scope : { showWarn : "=" },
*/
controller : function($scope) {
$scope.bb = {};
this.setset = function(nn) {
$scope.bb=nn;
};
}
});
当您使用scope:true
时,您可以直接访问scope
那么有什么问题?scope:true将创建一个子作用域,该子作用域将典型地从其父作用域继承,因此您将能够访问指令中父作用域上定义的值。@Satpal:我知道这一点,但就我的目的而言,这是建立通信的一种相当不雅的方式。事实上,您刚才共享的链接说:“两个控制器通过$scope继承共享信息被认为是不好的形式。”我将在我的问题中添加一个用例示例。@Satpal有时需要一个类似绑定设计的组件(例如,指令通信的接口),用于与其他作用域一起使用的指令:true指令,但由于新/隔离作用域的非法组合,隔离作用域无法使用。谢谢!这看起来很有希望。今天晚些时候我会试一试。谢谢,你的回答帮助很大。但我的问题的解决方案实际上似乎要简单得多。关键是您对范围的使用。$eval
。老实说,我不确定您的代码的其余部分要完成什么,但我想知道请参阅我的调整后的解决方案:$eval此处不建立真正的双重绑定,而只是复制对象引用,因此它对非对象值(标量,如字符串、数字、对象引用)不起作用。您对此进行了测试吗?我认为这是在正确的轨道上,但正如所写的那样,它将导致一个无限的摘要循环。如果查看-search中的“case:'='”,您会发现它们引入了一些额外的逻辑来防止这种情况。这个小组最好的答案,是的,我正在使用它,但到目前为止只有一个例子。我没有见过任何无限循环类型的行为。我明白你的意思,但是,如果远程值改变,那么观察者将设置本地值,这将触发本地观察者并设置远程值,依此类推。然而,这似乎没有发生。也许$parse中有什么东西阻止了它。我会仔细看一看,谢谢。这个解决方案比$eval解决方案好,因为它也适用于基本值和对象引用。注意,这不再需要了。在1.5中,我认为bindToController现在接受散列的方式与scope接受散列的方式大致相同,它将通过双向绑定将值绑定到控制器。您可以将scope设置为false设置为true。要使用非对象模型,您应该使用解析:attr=“{model}}”或attr=“{{'string'}”为什么不在此处使用$parse$解析(attr.myModel)(此.$scope)
.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
};
});
angular.module('mymodule', []).directive('a', function($parse, $modal) {
return {
restrict : 'A',
scope : {
gg : "="
},
require : "b",
link : function(scope, element, attrs, bCtrl) {
scope.$watch('gg',function(gg){
bCtrl.setset(scope.gg);
}
}
}
});
angular.module('mymodule').directive('b', function($parse, $modal) {
return {
restrict : 'A',
/*
* scope : { showWarn : "=" },
*/
controller : function($scope) {
$scope.bb = {};
this.setset = function(nn) {
$scope.bb=nn;
};
}
});