【问题标题】:Why is `replace` property deprecated in AngularJS directives? [duplicate]为什么 AngularJS 指令中不推荐使用 `replace` 属性? [复制]
【发布时间】:2014-08-03 09:39:25
【问题描述】:

根据the API docs,指令的replace 属性已被弃用,因此在未来,所有指令都将使用当前默认的replace: false

这消除了开发人员替换元素指令的元素的能力,而没有明显替换此功能。

请参阅this plunk,了解元素指令在使用和不使用replace: true 的情况下如何工作的示例。

为什么这个有用的属性被弃用而没有替代品?

【问题讨论】:

  • 可能是为了性能和/或简单性:如果您不替换它,它会保留元素的属性。我注意到 angular 确实定义了像“ng-1402613834652”这样的道具(不是属性,被欺骗了)。如果 Angular 的其他部分可以获取元素的引用并且不必担心它会过时,那么在运行数据/视图更新时执行的交叉检查就会少得多。
  • 只是想补充一点,在链接函数中通过 $('selector').replaceWith(content) 替换是一个非常简单的解决方案,尽管不如“replace: true”好。它还假设jquery,不确定angular的jqLit​​e是否支持replaceWith。
  • 当我想通过指令动态地将 ng-click 添加到现有元素时,我实际上不得不使用它。 stackoverflow.com/questions/22116470/…

标签: javascript angularjs angularjs-directive


【解决方案1】:

来自 GitHub:

Caitp-- 它已被弃用,因为replace: true 存在已知的非常愚蠢的问题,其中许多问题无法以合理的方式真正解决。如果您小心并避免这些问题,那么您将获得更多权力,但为了新用户的利益,告诉他们“这会让您头疼,不要这样做”会更容易。

-- AngularJS Issue #7636

replace:true 已弃用

来自文档:

replace([已弃用!],将在下一个主要版本中删除 - 即 v2.0)

指定模板应该替换的内容。默认为false

  • true - 模板将替换指令的元素。
  • false - 模板将替换指令元素的内容。

-- AngularJS Comprehensive Directive API

另见 -- How to use the 'replace' feature for custom AngularJS directives?

【讨论】:

    【解决方案2】:

    我会说它已被删除是一件好事,因为它可以防止您将指令(组件)的内部工作原理暴露给外部世界。将您的模板视为一个影子 DOM,并将您的指令与普通的 HTML 元素(如按钮)进行比较。当您将鼠标悬停或单击它们时,您不会看到添加了所有类型的类以及将样式应用于这些元素。这一切都“隐藏”在里面。因为目前对 shadow DOM 的支持有些有限,所以它是一种解决方法,但它已经使您能够适应未来。

    【讨论】:

    • 表单的编码方式和需要替换的 SVG 元素存在问题。不过我同意,调试起来更困难。
    • 我必须努力学习。
    【解决方案3】:

    更新

    其中一位合作者表示不会删除它,但不会修复已知的错误。 https://github.com/angular/angular.js/commit/eec6394a342fb92fba5270eee11c83f1d895e9fb#commitcomment-8124407

    原创

    这是此更改的提交: https://github.com/angular/angular.js/commit/eec6394a342fb92fba5270eee11c83f1d895e9fb

    replace 标志用于定义替换元素的指令 它们所在的位置将在下一个主要角度版本中删除。 此功能具有困难的语义(例如属性如何合并) 与它解决的问题相比,会导致更多的问题。此外,与 WebComponents 在 DOM 中有自定义元素是很正常的。

    在我看来,它是复杂性与维持支持的好处的结合。

    显然,开发人员使用它的原因之一是他们更喜欢注入语义正确的标记,从而替换自定义指令标记。


    阅读该链接下方的 cmets,显然很多人希望它保留。

    【讨论】:

    • 最后的 cmets 给我们带来了好消息,replace 不会被删除 :)
    • 我在 angularJS 1.3.0 上,看起来它被删除了
    • Edgar:它在 1.3.0 中没有被删除。
    • 我在更换自己时遇到了问题,甚至准备了一个 PR 来修复它们:github.com/angular/angular.js/pull/10733。此 PR 的讨论线程包含一些有趣的观点,说明 replace 被破坏的原因以及如何解决它导致的一些问题。
    • 这令人失望。我发现当你的指令模板包含并且包含层次相关的元素(如 ul|ol/li)时,替换是必不可少的。我使用替换来确保构造诸如菜单之类的指令的标记以及带有 ul/li 之类的东西的标记最终会得到实际有效的标记。我真的希望 WebComponents(我没有进行太多研究)有另一种解决此类问题的方法
    【解决方案4】:

    如果您担心replace: true 会在下一个版本中被删除,您可以使用postCompile 函数来复制该行为。

    /// Replace element with it's first child
    Utils.replaceWithChild = function(element) {
        var child = angular.element(element[0].firstChild);
        Utils.mergeAttributes(element, child);
        element.replaceWith(child);
    }
    
    /// Copy attributes from sourceElement to targetElement, merging their values if the attribute is already present
    Utils.mergeAttributes = function(sourceElement, targetElement) {
        var arr = sourceElement[0].attributes;
        for(var i = 0; i < arr.length; i++) {
            var item = arr[i];
            if(!item.specified)
                continue;
    
            var key = item.name;
            var sourceVal = item.value;
            var targetVal = targetElement.attr(key);
    
            if(sourceVal === targetVal)
                continue;
    
            var newVal = targetVal === undefined
                ? sourceVal
                : sourceVal + ' ' + targetVal;
    
            targetElement.attr(key, newVal);
        }
    }
    
    angular.module('test')
    .directive('unwrap', function() {
        return {
            restrict: 'AE',
            templateUrl: 'unwrap.part.html',
            compile: function() {
                return function postCompile(scope, element, attr) {
                    Utils.replaceWithChild(element);
                };
            }
        }; 
    });
    

    【讨论】:

    • 这不是一个好的解决方案,因为替换不推荐用于概念而不是功能,我们通常没有任何用于指令元素的 css,然后我们看不到主要元素的任何效果
    • @Ali.MD 在某些情况下,您想装饰(阅读:添加功能)某些元素,但将其包装在另一个 div 中会导致麻烦。如果你想使用多个装饰器,html 结构会发生巨大变化,结果你可能会损坏 css 或 javascript。
    • 一个很好的例子是容器组件(想想 React)。
    猜你喜欢
    • 2016-05-31
    • 2015-09-02
    • 2013-08-02
    • 2021-09-12
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 2013-11-06
    相关资源
    最近更新 更多