AngularJS 指令属性的多种用法
AngularJS directive attributes multiple usages
我有以下 HTML:
<my-dom attri="something 01">content 01</my-dom>
<my-dom attri="something 02">content 02</my-dom>
<my-dom attri="something 03">content 03</my-dom>
现在我希望在运行时将其替换为:
<div>something 01: content 01</div>
<div>something 02: content 02</div>
<div>something 03: content 03</div>
因此我创建了这个 AngularJS 指令:
app.directive('myDom', function() {
var content;
return {
restrict: 'EA',
replace: true,
scope : true,
// scope : false,
// scope: {},
template: function(elem, attr){
content = elem.clone();
return '<div>{{myContent}}: {{oldContent}}</div>';
},
controller: function(){
},
link: {
pre: function(scope, elem, attr){
scope.myContent = content.attr("attri"); // could also use "attr"
scope.oldContent= content.html(); // could not use "elem" or "attr"
},
post: function(scope, elem, attr){
},
}
};
});
这里我首先克隆私有变量"content"中的原始DOM元素,然后用新元素替换DOM元素。在这个新的 HTML 标签中,我插入了旧代码中的属性数据。但这里有点混乱:
输出代码为:
<div>something 03: content 03</div>
<div>something 03: content 03</div>
<div>something 03: content 03</div>
所以范围有问题。但是什么?
根据文档,scope : true
正在通过继承父作用域为指令创建一个新作用域。
父作用域的变化确实会影响指令作用域,但指令作用域的变化不会改变父作用域。
我唯一能想到的:
这个指令只有一个范围。所以 <my-dom>
的所有三种用法共享同一个作用域。
那是对的吗?我怎样才能得到我想要的结果?
正如我在评论中提到的,您的 content
在所有指令实例之间共享,因此它在每个模板函数中被覆盖。
要实现所需的行为,您可以使用 transcludeFn
together with transclude: true
访问用您的指令包装的元素,请参见下面的示例:
angular.module('plunker', [])
.controller('MainCtrl', function ($scope) {
})
.directive('myDom', function () {
return {
restrict: 'EA',
replace: true,
transclude: true,
scope: true,
template: '<div>{{myContent}}: {{oldContent}}</div>',
controller: function () {
},
link: {
pre: function (scope, elem, attr, ctrl, transclude) {
transclude(function (clone) {
scope.myContent = attr["attri"];
scope.oldContent = clone.text();
});
}
}
};
});
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
<body ng-app="plunker">
<div ng-controller="MainCtrl">
<my-dom attri="something 01">content 01</my-dom>
<my-dom attri="something 02">content 02</my-dom>
<my-dom attri="something 03">content 03</my-dom>
</div>
</body>
this SO question中的一些更有趣的答案和示例。
我有以下 HTML:
<my-dom attri="something 01">content 01</my-dom>
<my-dom attri="something 02">content 02</my-dom>
<my-dom attri="something 03">content 03</my-dom>
现在我希望在运行时将其替换为:
<div>something 01: content 01</div>
<div>something 02: content 02</div>
<div>something 03: content 03</div>
因此我创建了这个 AngularJS 指令:
app.directive('myDom', function() {
var content;
return {
restrict: 'EA',
replace: true,
scope : true,
// scope : false,
// scope: {},
template: function(elem, attr){
content = elem.clone();
return '<div>{{myContent}}: {{oldContent}}</div>';
},
controller: function(){
},
link: {
pre: function(scope, elem, attr){
scope.myContent = content.attr("attri"); // could also use "attr"
scope.oldContent= content.html(); // could not use "elem" or "attr"
},
post: function(scope, elem, attr){
},
}
};
});
这里我首先克隆私有变量"content"中的原始DOM元素,然后用新元素替换DOM元素。在这个新的 HTML 标签中,我插入了旧代码中的属性数据。但这里有点混乱:
输出代码为:
<div>something 03: content 03</div>
<div>something 03: content 03</div>
<div>something 03: content 03</div>
所以范围有问题。但是什么?
根据文档,scope : true
正在通过继承父作用域为指令创建一个新作用域。
父作用域的变化确实会影响指令作用域,但指令作用域的变化不会改变父作用域。
我唯一能想到的:
这个指令只有一个范围。所以 <my-dom>
的所有三种用法共享同一个作用域。
那是对的吗?我怎样才能得到我想要的结果?
正如我在评论中提到的,您的 content
在所有指令实例之间共享,因此它在每个模板函数中被覆盖。
要实现所需的行为,您可以使用 transcludeFn
together with transclude: true
访问用您的指令包装的元素,请参见下面的示例:
angular.module('plunker', [])
.controller('MainCtrl', function ($scope) {
})
.directive('myDom', function () {
return {
restrict: 'EA',
replace: true,
transclude: true,
scope: true,
template: '<div>{{myContent}}: {{oldContent}}</div>',
controller: function () {
},
link: {
pre: function (scope, elem, attr, ctrl, transclude) {
transclude(function (clone) {
scope.myContent = attr["attri"];
scope.oldContent = clone.text();
});
}
}
};
});
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
<body ng-app="plunker">
<div ng-controller="MainCtrl">
<my-dom attri="something 01">content 01</my-dom>
<my-dom attri="something 02">content 02</my-dom>
<my-dom attri="something 03">content 03</my-dom>
</div>
</body>
this SO question中的一些更有趣的答案和示例。