数据绑定指令的想法是一个有趣的想法,但我不会这样做,因为我相信您会遇到指令优先级问题,而且它非常不标准并且会使您的代码难以为未来的程序员遵循。有几种方法可以做到这一点,所以我将讨论我使用过的 3 种不同的解决方案。
解决方案 1
如果您只需要一种方式的数据绑定,最简单的解决方案是在使用 {{}} 在其上插入任何简单的范围变量之后,对指令内对象的字符串表示形式使用 angular 的 scope.$eval 函数。字符串表示甚至不必是有效的 JSON,因为您会注意到在下面的示例中我没有在对象键周围包含引号。
在视图中:
<div databinding="{one:'first', two:{{scopeVar}}, complex:[1,2, "Hi"]}"></div>
在javascript中:
app.directive('databinding', function () {
return{
link: function (scope, elm, attrs) {
console.debug(scope.$eval(attrs['databinding']));
}
}
});
解决方案 2
另一种单向数据绑定解决方案是在控制器内部创建一个选项对象,并使用“@”(甚至“=”)将其传递给指令:
在控制器中:
$scope.options = {one: "first, two: "second"};
在视图中:
<div databinding="options"></div>
在javascript中:
app.directive('databinding', function () {
return{
scope: {
options: "@" //Can also use = here
},
link: function (scope, elm, attrs) {
console.log(scope.options);
}
}
});
解决方案 3
如果您确实需要双向数据绑定,那么您很不走运,因为没有优雅的方法可以做到这一点。但是,如果您在市场上寻找 hackish 解决方案,您可以使用与解决方案 2 非常相似但更改选项对象的方法来完成双向数据绑定。
与其声明包含简单原始数据类型(如字符串)的选项对象,不如在选项对象内创建一个虚拟对象,然后在其中声明变量。这样做,控制器中范围变量的更改也将在指令内实现,如超时所示。
控制器:
$scope.someScopeVar = "Declared in controller"
$scope.options = {
dummy: {
one: $scope.someScopeVar,
two: "second"
}
}
window.setTimeout(function(){
$scope.someScopeVar = "Changed in controller";
}, 2000)
看法:
<div databinding="options"></div>
指示:
app.directive('databinding', function () {
return{
scope: {
options: "=" //You need to use = with this solution
},
link: function (scope, elm, attrs) {
console.log(scope.options.dummy.one); //Outputs "Declared in controller"
window.setTimeout(function(){
console.log(scope.options.dummy.one) //Outputs "Changed in controller"
}, 5000)
}
}
});
此方法有效,因为 javascript 通过引用传递对象,而原语被复制。通过将对象嵌套在对象中,可以保留数据绑定。