gpt4 book ai didi

javascript - 没有 watch 的 Angular 一次性绑定(bind)

转载 作者:行者123 更新时间:2023-11-30 06:51:10 25 4
gpt4 key购买 nike

我在使用 Angular 的一次性绑定(bind)时遇到了问题。

假设我想将 ngIf 与一次性绑定(bind)一起使用,如下所示:

<div ng-if="::showImage">
<img src="somesource" img-preloader/>
</div>

在这种情况下,angular 会为 if 中的表达式创建一个 watch。一旦它被解析为一个非未定义的值, watch 就会被删除。

如果仅将其解析为真值,则后代 html 树将添加到 DOM 并随后呈现。

现在这一切都很好,但我真的很想避免初始监视,只是解析表达式,如果它未定义 - 然后才设置一个监视。在我的场景中存在的原因相当复杂,但基本上我有一些机制可以暂时禁用不需要的 watch ......

所以我一直在寻找内置 Angular 一次性绑定(bind)的替代方案,并遇到了 angular-once .

Angular-once 以不同的方式实现一次性绑定(bind),它仅在表达式被解析为未定义时才设置临时监视,因此如果它在初始尝试中解析,则不会创建监视。听起来很棒。

所以我可以这样做:

<div once-if="showImage">
<img src="somesource" img-preloader/>
</div>

但是,这就是问题所在 - 显然,后代 HTML 树首先默认呈现,然后如果 once-if 解析为 false,则后代节点将从 DOM 中删除。

这是实现它的代码片段:

{
name: 'onceIf',
priority: 600,
binding: function (element, value) {
if (!value) {
element.remove();
}
}
},

这对我来说是不好的行为,因为创建后代树是不行的并且会导致其他问题,例如 - 在上面的示例中将下载 img。

所以我正在寻找一种方法来在像 ngIf 这样的指令中进行一次性绑定(bind),而无需设置监视表达式是否成功解析并且无需预渲染后代树。

最佳答案

我试图避免这种情况,但现在我最终实现了基于 Angular 标准指令但具有必要的附加功能的自定义指令。

ngIf 派生指令:

app.directive('watchlessIf', ['$animate', '$compile', '$parse', function($animate, $compile, $parse) {
return {
multiElement: true,
transclude: 'element',
priority: 600,
terminal: true,
restrict: 'A',
$$tlb: true,
link: function($scope, $element, $attr, ctrl, $transclude) {
function valueChangedAction(value) {
if (value) {
if (!childScope) {
$transclude(function(clone, newScope) {
childScope = newScope;
clone[clone.length++] = $compile.$$createComment('end watchlessIf', $attr.watchlessIf);
block = {
clone: clone
};
$animate.enter(clone, $element.parent(), $element);
});
}
} else {
if (previousElements) {
previousElements.remove();
previousElements = null;
}
if (childScope) {
childScope.$destroy();
childScope = null;
}
if (block) {
previousElements = getBlockNodes(block.clone);
$animate.leave(previousElements).then(function() {
previousElements = null;
});
block = null;
}
}
}

var block, childScope, previousElements;
if ($attr.watchlessIf.startsWith("::")) {
var parsedExpression = $parse($attr.watchlessIf)($scope);
if (parsedExpression != null) {
valueChangedAction(parsedExpression);
return;
}
}

$scope.$watch($attr.watchlessIf, valueChangedAction);
}
};
}]);

ngBind 派生指令:

app.directive('watchlessBind', ['$compile', '$parse', function($compile, $parse) {
return {
restrict: 'AC',
compile: function watchlessBindCompile(templateElement) {
$compile.$$addBindingClass(templateElement);
return function watchlessBindLink(scope, element, attr) {
function valueChangedAction(value) {
element.textContent = (typeof value == "undefined") ? '' : value;
}

$compile.$$addBindingInfo(element, attr.watchlessBind);
element = element[0];
if (attr.watchlessBind.startsWith("::")) {
var parsedExpression = $parse(attr.watchlessBind)(scope);
if (parsedExpression != null) {
valueChangedAction(parsedExpression);
return;
}
}

scope.$watch(attr.watchlessBind, valueChangedAction);
};
}
};
}]);

注意事项:

  • 不幸的是,对于这种方法,我将不得不为其他 Angular 指令以及我希望支持潜在的 watch-less 一次性绑定(bind)的地方实现类似的指令。

  • 我在指令中使用私 Angular 东西,比如 $$tlb 选项,虽然我真的不应该......

关于javascript - 没有 watch 的 Angular 一次性绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46947606/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com