简体   繁体   English

为什么Angular会弃用旧的“替换”指令选项?

[英]Why did Angular deprecate the old “replace” directive option?

In the old Angular 1.x we could build directives and have an options to set "replace": true in the configuration which would allow you to tell Angular to replace the entire DOM element with whatever your directive was comprised of. 在旧的Angular 1.x中,我们可以构建指令并有一个选项来设置“replace”:在配置中为true,这将允许您告诉Angular用您的指令所包含的任何内容替换整个DOM元素。

I am fairly new to Angular 2+, but so far we only seem to have 2 options for building a component in the same manner: 我是Angular 2+的新手,但到目前为止,我们似乎只有2个以相同方式构建组件的选项:

1) Use the element selector like this <app-my-component></app-my-component> 1)使用像<app-my-component></app-my-component>这样的元素选择器

2) Use the attribute selector like this <div app-my-component></div> 2)使用属性选择器,如<div app-my-component></div>

The issue is I see problems with both of these: 问题是我发现这两个问题:

Using method #1 can disrupt CSS stylings as Angular will place an extra DOM element into the page which means if you have an HTML structure like comprised of a <ul> and children <li> elements and you want to make the <li> elements a reusable component then your resulting DOM looks like this: 使用方法#1可以破坏CSS样式,因为Angular会在页面中放置一个额外的DOM元素,这意味着如果你有一个像<ul>和children <li>元素组成的HTML结构,你想要制作<li>元素一个可重用的组件,然后您生成的DOM如下所示:

<ul>
    <app-my-component>
        <li>Inner</li>
    </app-my-component>
</ul>

Which would effectively break any CSS targeting ul > li . 这将有效打破任何CSS目标ul > li

Using method #2 allows us to fix the CSS styling issue, but removes the abstraction that a component is supposed to provide as now a consumer of the component has to have knowledge about the element type needed: 使用方法#2允许我们修复CSS样式问题,但是删除组件应该提供的抽象,因为现在组件的使用者必须知道所需的元素类型:

<ul>
    <li app-my-component>
        Inner
    </li>
</ul>

In the above case the developer has to know to use a <li> in order for things to work properly. 在上述情况下,开发人员必须知道使用<li>才能使事情正常工作。 This is a very simple example, but more complex scenarios could be less intuitive to the developer causing headaches. 这是一个非常简单的示例,但更复杂的情况对于开发人员来说可能不太直观,从而导致头痛。

Take a look at this example. 看看这个例子。 Due to the nature of the underlying HTML/CSS I had to setup these 2 (primary/secondary) components like this and use an internal <ng-content> to display the navigation correctly. 由于底层HTML / CSS的性质,我必须设置这样的2(主要/次要)组件,并使用内部<ng-content>来正确显示导航。 As you can see having to stick <li> elements inside of the parent <div> looks and feels weird and adds the need for the developer to know about the underlying HTML. 正如您所看到的那样,必须在父<div>粘贴<li>元素,看起来很奇怪,并且需要开发人员了解底层HTML。

<div app-platform-navigation-primary label="Test" icon="account_box" link="#">
    <li app-platform-navigation-secondary label="Test2" link="#"></li>
    <li app-platform-navigation-secondary label="Test3" link="#"></li>
    <li app-platform-navigation-secondary label="Test4" link="#"></li>
    <li app-platform-navigation-secondary label="Test5" link="#"></li>
</div>

Summary 摘要

Overall, both methods have their pros and cons, but I feel like I could get the best of both worlds if we could still use the "replace" method which allows you to develop using method #1 which provides all of the abstraction you need, but would not add an "extra" DOM element onto the page which would allow CSS to continue to work. 总的来说,这两种方法各有利弊,但我觉得如果我们仍然可以使用“替换”方法,我可以充分利用这两种方法,这种方法允许你使用方法#1开发,它提供了你需要的所有抽象,但不会在页面上添加“额外”DOM元素,这将允许CSS继续工作。

What were the downfalls of doing this that caused the Angular team to remove these capabilities? 这样做的弊端是什么导致Angular团队取消了这些功能? And is there any solution to do it how I would like to do it? 是否有任何解决方案可以做到这一点我想做什么?

When developers want to use your component, they have to look at your documentation to see what the name of the selector is. 当开发人员想要使用您的组件时,他们必须查看您的文档以查看选择器的名称。 So what is the difference between you instructing the developers to use <app-my-component> vs <li app-my-component> ? 那么指导开发人员使用<app-my-component> vs <li app-my-component>之间的区别是什么? Note that component selectors support CSS selectors. 请注意,组件选择器支持CSS选择器。 In other words, you can ensure that your component only works with a <li> host element: 换句话说,您可以确保您的组件仅适用于<li>主机元素:

@Component({
  selector: 'li[app-my-component]'
  ...
})

With a strict selector as shown, where you specify both the element and the attribute, you can prevent developers from using your component outside of its intended use. 使用如图所示的严格选择器,您可以指定元素和属性,可以防止开发人员在预期用途之外使用您的组件。

For your example use case: 对于您的示例用例:

@Component({
  selector: 'ul[app-platform-navigation-primary]'
  ...
})

and.. 和..

@Component({
  selector: 'li[app-platform-navigation-secondary]'
  ...
})

The host element of a component does not have to be a <div> . 组件的主机元素不必是<div> It can be a <ul> , <li> or whatever else. 它可以是<ul><li>或其他任何东西。

If you wish to abstract the fact that your component is using <ul> and <li> internally, then take a look at this SO answer . 如果您希望抽象出组件在内部使用<ul><li>的事实,那么请看一下这个SO答案 This answer demonstrates how you can wrap each child component inside <li> s within your parent component. 这个答案演示了如何将每个子组件包装在父组件中的<li>

In summary, it is possible to achieve the same result as in AngularJs where you do not have extra elements but without the use of replace . 总之,可以在AngularJs中获得与没有额外元素但不使用replace结果相同的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM