【问题标题】:How to remove extra wrapping elements in the rendered HTML?如何在呈现的 HTML 中删除额外的包装元素?
【发布时间】:2018-08-30 23:42:39
【问题描述】:

我在 3 天前开始学习 Angular 5,所以我对它很陌生。我还使用 angularJS 和 React 来开发应用程序,我想我不明白 angular 5 组件是如何完全工作的。例如,如果我创建一个自定义按钮,其中包含自定义文本(我并不是说应该这样做,但这是一个简单的示例,说明了我的观点),如下所示:

<app-button>
  <app-text>
    My Text
  </app-text>
</app-button>

渲染的 DOM 结果:

<app-button>
  <button>
    <app-text>
      <span>
        My Text
      </span>
    </app-text>
  </button>
</app-button>

这是不可读的,我想知道是否有办法删除这个包装元素,只需放置组件布局替换标签,从而得到以下结构:

<button>
  <span>
    My Text
  </span>
</button>

如果无法删除它们,您有什么建议?谢谢!

【问题讨论】:

    标签: javascript css angular typescript components


    【解决方案1】:

    Angular 组件是带有模板的指令。 According to this:

    指令配置@Directive({property1: value1, ... })

    selector: '.cool-button:not(a)' 指定一个 CSS 选择器 在模板中标识此指令。支持的选择器 包括元素、[属性]、.class 和 :not()。

    所以组件选择器也可以是属性选择器。对于您的示例,而不是这样写:

    parent.component.html:

    <app-button>
      <app-text>
        My Text
      </app-text>
    </app-button>
    

    写这个:

    parent.component.html:

    <button app-button>
        <span app-text>My Text</span>
    </button>
    

    在哪里:

    app-button.component.ts

    ...  
      selector: '[app-button]',
      template: `<ng-content></ng-content>
    ...
    

    app-text.component.ts

    ...
      selector: '[app-text]',
      template: `<ng-content></ng-content>`
    ...
    

    这将按照您的预期呈现:

    在您对这些按钮的样式发表评论后更新:

    要从按钮组件内部设置按钮样式,并在父组件中设置类,请使用:host-context 伪类。它没有被弃用并且运行良好

    button.component.css

      :host-context(.button-1)  {
        background: red;
      }
      :host-context(.button-2)  {
          background: blue;
      }
    

    app.component.html

    <button app-button class="button-1">
        <span app-text>My Text</span>
    </button>
    
    <button app-button class="button-2">
        <span app-text>My Text</span>
    </button>
    

    这里是DEMO

    【讨论】:

    • 谢谢!问题是我仍然会有一个不必要的span 包裹我的按钮。通过查看您的代码,我想我可以改写 &lt;button app-button&gt; 并将应用程序按钮的模板制作为 &lt;ng-content&gt;&lt;/ng-content&gt; 但如果我这样做,我将不得不在通用样式表中定义按钮样式,因为组件样式仅适用到模板,我无法从组件样式内部使用我的指令定位按钮。
    • 嗯,我查过了。现在假设我有两种类型的按钮.button-1 有蓝色背景和.button-2 有红色背景。我想要做的是使用 2 个选项将 styles.css 添加到按钮组件。并在 app.layout 中执行:&lt;button app-button class="button-1"&gt;&lt;ng-container app-text&gt;My Text&lt;/ng-container&gt;&lt;/button&gt;。我看到的问题是“.button-1”样式必须放在app.component.css中,不能放在button.component.css中,所以我必须在使用的每个视图中声明这些样式一个按钮
    • 因为样式是组件范围的。顺便问一下,您在那里添加的ng-container 是什么?是不是添加模板时去掉的虚拟组件?
    • 我认为这是解决我的问题的有效方法。我会尽快添加完整的回复!非常感谢您的帮助!
    • 我对这种方法的一个问题是封装的破坏。您是否知道保留它的方法,并且仍然在子组件中定义所有样式?显然github.com/angular/angular/issues/18877 在这个话题上是开放的,但似乎卡住了
    【解决方案2】:

    我遇到了类似的问题。如果其他人有同样的问题,我会提供我的解决方案。

    我的组件应该能够在其他组件中使用或作为来自&lt;router-outlet&gt;&lt;/router-outlet&gt; 的路由。当我将选择器用作[my-component] 属性时,只要在其他组件中使用它,事情就可以完美运行。但是当&lt;router-outlet&gt;&lt;/router-outlet&gt;创建时&lt;div&gt;是自动创建的。

    为避免这种情况,我们可以简单地使用多个选择器,并考虑可以组合选择器。

    考虑一下:我希望我的组件使用属性my-component,如果它应该由&lt;router-outlet&gt;&lt;/router-outlet&gt; 创建,它应该被包装在&lt;section&gt;&lt;/section&gt; 中。要实现这一点,只需使用:

    @Component(
        selector: 'section[my-component], my-component',
        ...
    )
    

    如果在另一个标签中使用,结果将是:

    <whatevertag my-component>
         ... component content ...
    </whatertag>
    

    如果用作路线:

    <section my-component>
         ... component content ...
    </section>
    

    【讨论】:

      猜你喜欢
      • 2019-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-22
      • 2013-04-19
      • 2020-03-20
      • 2013-10-16
      • 1970-01-01
      相关资源
      最近更新 更多