为什么 AngularJS 指令中不推荐使用`replace` 属性?

IT技术 javascript angularjs angularjs-directive
2021-02-04 00:47:29

根据API 文档,指令的replace属性已弃用,因此将来所有指令都将使用当前默认值replace: false.

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

请参见本普拉克为元素指示如何与不工作的例子replace: true

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

4个回答

更新

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

原来的

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

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

对我来说,这听起来像是维持支持的复杂性与好处的结合。

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


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

我在 angularJS 1.3.0 上,看起来它已被删除
2021-03-24 00:47:29
这令人失望。我发现当你的指令模板被嵌入时,替换是必不可少的,并且包含像 ul|ol/li 这样的分层依赖元素。我使用 replace 来确保构造菜单等内容的指令的标记最终以实际工作的标记结束。我真的希望 WebComponents(我没有研究太多)有一种替代方法来解决这样的问题
2021-04-01 00:47:29
我遇到了更换自己的问题,甚至准备了一个 PR 来修复它们:github.com/angular/angular.js/pull/10733这个 PR 的讨论主题包含一些有趣的观点,关于为什么替换被破坏以及如何解决它导致的一些问题。
2021-04-03 00:47:29
Edgar:它没有在 1.3.0 中删除。
2021-04-04 00:47:29
最后的评论对我们来说是个好消息,替换不会被删除:)
2021-04-10 00:47:29

如果您担心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 然后我们看不到主要元素的任何效果
2021-03-24 00:47:29
@Ali.MD 在某些情况下,您想装饰(阅读:向其添加功能)某些元素,但将其包装在另一个 div 中会导致麻烦。如果您想使用多个装饰器,html 结构将发生巨大变化,因此您可能会损坏 css 或 javascript。
2021-03-30 00:47:29
一个很好的例子是容器组件(想想 React)。
2021-04-09 00:47:29

来自 GitHub:

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

-- AngularJS 问题 #7636

replace:true 已弃用

从文档:

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

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

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

-- AngularJS 综合指令 API

另请参阅-如何为自定义 AngularJS 指令使用“替换”功能?

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

我必须以艰难的方式学习这一点。
2021-03-25 00:47:29
表单编码方式和需要替换的 SVG 元素存在问题。但是,我同意,调试起来更难。
2021-04-06 00:47:29