Angularjs 如何使angular.js重新评估/重新编译内部html?
我正在制作一个指令来修改它的内部html。迄今为止的代码:Angularjs 如何使angular.js重新评估/重新编译内部html?,angularjs,angularjs-directive,interpolation,Angularjs,Angularjs Directive,Interpolation,我正在制作一个指令来修改它的内部html。迄今为止的代码: .directive('autotranslate', function($interpolate) { return function(scope, element, attr) { var html = element.html(); debugger; html = html.replace(/\[\[(\w+)\]\]/g, function(_, text) { re
.directive('autotranslate', function($interpolate) {
return function(scope, element, attr) {
var html = element.html();
debugger;
html = html.replace(/\[\[(\w+)\]\]/g, function(_, text) {
return '<span translate="' + text + '"></span>';
});
element.html(html);
}
})
指令('autotranslate',函数($interpolate){
返回函数(范围、元素、属性){
var html=element.html();
调试器;
html=html.replace(/\[\[(\w+)\]\]\]/g,函数(\,文本){
返回“”;
});
html(html);
}
})
它可以工作,只是内部html不是由angular计算的。我想重新评估元素的子树。有办法吗
谢谢:)您必须$compile
像
.directive('autotranslate', function($interpolate, $compile) {
return function(scope, element, attr) {
var html = element.html();
debugger;
html = html.replace(/\[\[(\w+)\]\]/g, function(_, text) {
return '<span translate="' + text + '"></span>';
});
element.html(html);
$compile(element.contents())(scope); //<---- recompilation
}
})
指令('autotranslate',函数($interpolate,$compile){
返回函数(范围、元素、属性){
var html=element.html();
调试器;
html=html.replace(/\[\[(\w+)\]\]\]/g,函数(\,文本){
返回“”;
});
html(html);
$compile(element.contents())(scope);//这比@Reza的解决方案效果更好
.directive('autotranslate', function() {
return {
compile: function(element, attrs) {
var html = element.html();
html = html.replace(/\[\[(\w+)\]\]/g, function(_, text) {
return '<span translate="' + text + '"></span>';
});
element.html(html);
}
};
})
.directive('autotranslate',function(){
返回{
编译:函数(元素、属性){
var html=element.html();
html=html.replace(/\[\[(\w+)\]\]\]/g,函数(\,文本){
返回“”;
});
html(html);
}
};
})
当scope
是它所有子元素的作用域时,Reza的代码工作。但是,如果此指令的某个子节点中有ng控制器或其他内容,则找不到作用域变量。但是,使用此解决方案^,它只起作用!这里有一个更通用的方法来解决此问题:
angular.module('kcd.directives').directive('kcdRecompile', function($compile, $parse) {
'use strict';
return {
scope: true, // required to be able to clear watchers safely
compile: function(el) {
var template = getElementAsHtml(el);
return function link(scope, $el, attrs) {
var stopWatching = scope.$parent.$watch(attrs.kcdRecompile, function(_new, _old) {
var useBoolean = attrs.hasOwnProperty('useBoolean');
if ((useBoolean && (!_new || _new === 'false')) || (!useBoolean && (!_new || _new === _old))) {
return;
}
// reset kcdRecompile to false if we're using a boolean
if (useBoolean) {
$parse(attrs.kcdRecompile).assign(scope.$parent, false);
}
// recompile
var newEl = $compile(template)(scope.$parent);
$el.replaceWith(newEl);
// Destroy old scope, reassign new scope.
stopWatching();
scope.$destroy();
});
};
}
};
function getElementAsHtml(el) {
return angular.element('<a></a>').append(el.clone()).html();
}
});
编辑
如果您正在看这个,我会认真地建议您查看版本,因为它可能更为最新。我使用它的目的是:重新编译已编译的元素是不正确的(请参阅下面@kornbridge的解决方案中报告的问题).@jerico在link
函数中,除非您使用compile
函数,否则在操作DOM
时必须重新编译。您提到了@kornbridge的解决方案,他使用了compile
函数。根据文档,我认为这不是使用compile的合适用例e> 函数。@Reza:IMO编译函数可以工作,但也不是最好的解决方案。OP的意图可能最好通过在服务器上或编译前操作标记来实现。这是一个高性能和稳定的解决方案,因为它完全消除了在翻译中对角度绑定的需要。请参阅Google的t(在视频中大约从42:34开始)。@Reza:您引用的文档说明编译函数是为了操纵标记的结构,而链接函数只是为了将其绑定到一个范围。由于OP想要操纵标记,包括绑定,我想说这显然是编译函数的一个用例(但在这种特殊情况下,请参阅我的其他评论,以获得更好的解决方案)。@Adam Barthelson,哈哈,谢谢:-)事实上,我最近在我的网站上更新了这个。所以我建议查看一下网站的版本。这个指令可以用来触发angular 1.2中的重新遵从吗?我必须使用angular 1.3中的一次性绑定表达式吗?有人能解释我:返回angular.element(“”).append(el.clone()).html();
是,html()
返回元素的内容。因为我们还需要el
的根节点,所以我们首先将其插入一个伪元素中,然后获取该元素的内容。从指令中访问$parent作用域会破坏封装。如果要这样做,则需要一个parent指令(请参见Angular Direction配置对象的require属性)以支持的方式建立这种依赖关系。@kornifridge您能否清楚地说明当作用域是它所有子元素的作用域时,Reza的代码起作用?它是如何更好地工作的?根据文档,使用compile
函数的最佳实践是可以在directi实例之间共享的任何操作出于性能原因,应将ves移到编译函数。
<div kcd-recompile="recompile.things" use-boolean>
<div ng-repeat="thing in ::things">
<img ng-src="{{::thing.getImage()}}">
<span>{{::thing.name}}</span>
</div>
</div>
$scope.recompile = { things: false };
$scope.$on('things.changed', function() { // or some other notification mechanism that you need to recompile...
$scope.recompile.things = true;
});