当前位置: 首页 > 知识库问答 >
问题:

角度一次绑定没有手表

穆招
2023-03-14

我对Angular的一次性绑定有困难。

假设我想将ngIf与一次性绑定结合使用,如下所示:

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

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

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

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

所以我在寻找替代内置angular的一次性绑定的方法,并且遇到过angular一次。

Angular once以另一种方式实现一次绑定,它仅在表达式被解析为未定义时设置临时监视,因此如果它在初始尝试中解析,则不会创建监视。听起来不错。

所以我可以这样做:

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

但是,问题就在这里——显然后代超文本标记语言树首先默认呈现,然后如果once-if解析为false,后代节点将从DOM中删除。

下面是一段代码:

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

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

因此,我正在寻找一种方法,在ngIf等指令中执行一次性绑定,如果表达式成功解析,则无需设置监视,也无需预呈现子树。

共有1个答案

蒋航
2023-03-14

我试图避免这种情况,但现在我最终实现了基于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);
            };
        }
    };
}]);

备注:

>

  • 不幸的是,使用这种方法,我必须为其他角度指令实现类似的指令,如果我想支持潜在的少看一次绑定的话。

    我在指令中使用私有角度的东西,比如$$tlb选项,尽管我真的不应该。。。

  •  类似资料:
    • AngularJS自1.3.0-beta.10版本以来有一个新功能:“惰性一次性绑定”。 简单表达式的前缀可以是<代码>:: ,告诉angular在首次计算表达式后停止监视。给出的常见示例如下: 下面的表达式有类似的语法吗?

    • 问题内容: angular js中的“ ng-bind”和“一次性绑定”有什么区别? 如果有任何区别,我应该在哪里使用它们? 问题答案: 双向数据绑定 AngularJS中的双向数据绑定意味着将数据从模型绑定到视图,反之亦然(数据从范围/控制器流到视图,再从视图流到范围/控制器)。“ NG-模型 ”是用于实现双向数据绑定的角指令。无论范围是否要求更新数据,对范围/控制器对该模型的任何修改都将自动传

    • 应用程序。组成部分ts 应用程序。组成部分html 当我重新加载浏览器并检查日志时。角度重新记录4次。如果你知道为什么会这样,请告诉我。 链接闪电战:https://stackblitz.com/edit/angular-ivy-zqjr2d?file=src/app/app.component.ts

    • 问题内容: 自1.3.0-beta.10版本以来,AngularJS具有一项新功能:“懒惰的一次性绑定”。 可以在简单表达式的前面加上,告诉angular在首次评估表达式后停止观看。给出的常见示例如下所示: 类似以下表达式的语法是否类似? 问题答案: 是。您可以在每个表达式前添加,甚至可以在或中添加前缀: 实际上,代码只是检查表达式中的前两个字符是为了激活一次性绑定(然后将其删除,因此甚至不需要括

    • 必须这样做真的,真的很愚蠢: 我相信这会给我4美元的观察者...所以我正在寻找一个替代方案来避免像那样愚蠢。

    • 在构建期间,是否有方法使用角度本机翻译(国际化)机制来翻译锚文本(或者成员的属性)?JavaScript数据的结构和模板的HTML可以更改。 如果Angular本机国际化机制不能处理这些问题(但我想知道它们到底有什么用),那么还有什么其他解决方案可以帮助实现这样的翻译呢?我找到了ngx-translate库,但它提供的翻译可以在运行时动态更改,理想情况下,我不想增加动态解决方案监视所有翻译文本的不