删除由 angular 组件创建的主机 HTML 元素选择器
Remove the host HTML element selectors created by angular component
在angular 2中,svg-rect是一个创建rect的组件,如下所示,
<svg height="550" width="450" x="0" y="0">
<g id="svgGroup">
<svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</svg-rect>
<svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</svg-rect>
</g>
</svg>
但这不会呈现 rect,因为创建了特殊的元素标签。如果删除 svg-rect 标签,它会呈现 rect
<svg height="550" width="450" x="0" y="0">
<g id="svgGroup">
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</g>
</svg>
在Angular1.x中,有replace:'true'删除指令带有编译输出的标签。我们可以在 angular2 中实现相同的功能吗?
引用Angular 1 to Angular 2 Upgrade Strategy doc:
Directives that replace their host element (replace: true directives in Angular 1) are not supported in Angular 2. In many cases these directives can be upgraded over to regular component directives.
There are cases when regular component directives are not going to work, in those cases alternative approaches can be used. For example for svg see: https://github.com/mhevery/ng2-svg
另一种删除我使用的组件主机的方法。
指令remove-host
//remove the host of avatar to be rendered as svg
@Directive({
selector: '[remove-host]'
})
class RemoveHost {
constructor(private el: ElementRef) {
}
//wait for the component to render completely
ngOnInit() {
var nativeElement: HTMLElement = this.el.nativeElement,
parentElement: HTMLElement = nativeElement.parentElement;
// move all children out of the element
while (nativeElement.firstChild) {
parentElement.insertBefore(nativeElement.firstChild, nativeElement);
}
// remove the empty element(the host)
parentElement.removeChild(nativeElement);
}
}
使用这个指令;
<avatar [name]="hero.name" remove-host></avatar>
在 remove-host
指令中,nativeElement
的所有子元素都插入到宿主元素之前,然后移除宿主元素。
Sample Example Gist
根据用例,可能存在一些性能问题。
与其尝试摆脱宿主元素,不如将其转换为有效的 SVG 但在其他方面不受影响:而不是您的 元素选择器
selector: "svg-rect"
及其在模板中对应的元素:
template: `...<svg-rect>...</svg-rect>...`
切换到属性选择器:
selector: "[svg-rect]"
并将该属性添加到组元素标签中:
template: `...<g svg-rect>...</g>...`
这将扩展为:
<svg height="550" width="450" x="0" y="0">
<g id="svgGroup">
<g svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</g>
<g svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</g>
</g>
</svg>
这是将呈现的有效 SVG。
Plnkr
还有一种方法,我们可以从组件中取出组件的模板。
首先,我们创建组件,我们希望从浏览器渲染中删除它的标签(我们在这里不是要删除标签。)
@Component({
selector: 'tl-no-tag',
template: `
<template #tmp>
<p>{{value}}</p>
</template>`,
styleUrls: []
})
export class TlNoTagComponent {
@ViewChild('tmp') tmp: any;
value = 5;
}
然后,在另一个组件的模板中,我们写:
<tl-no-tag #source></tl-no-tag> <!-- This line can be placed anywhere -->
<template [ngTemplateOutlet]="source.tmp"></template> <!-- This line will be placed where needed -->
然后,我们在浏览器中有这样的东西:
<tl-no-tag></tl-no-tag>
<p>5</p>
因此,我们已经从 TlNoTagComponent 中取出 <p>{{value}}</p>
。 <tl-no-tag></tl-no-tag>
将继续存在,但不会阻止任何 css 或 svg-thing。
怎么样:
:host { display: contents; }
将其放入主机组件的 css(或 scss)文件中将导致组件的框不呈现。
N.B:它以前对我有用——但显然我会担心浏览器的兼容性问题,特别是如果您正在开发以支持旧版浏览器。我也很确定这并没有完全脱离 "experimental" 阶段。文档还指出这可能会导致可访问性问题。
在angular 2中,svg-rect是一个创建rect的组件,如下所示,
<svg height="550" width="450" x="0" y="0">
<g id="svgGroup">
<svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</svg-rect>
<svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</svg-rect>
</g>
</svg>
但这不会呈现 rect,因为创建了特殊的元素标签。如果删除 svg-rect 标签,它会呈现 rect
<svg height="550" width="450" x="0" y="0">
<g id="svgGroup">
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</g>
</svg>
在Angular1.x中,有replace:'true'删除指令带有编译输出的标签。我们可以在 angular2 中实现相同的功能吗?
引用Angular 1 to Angular 2 Upgrade Strategy doc:
Directives that replace their host element (replace: true directives in Angular 1) are not supported in Angular 2. In many cases these directives can be upgraded over to regular component directives.
There are cases when regular component directives are not going to work, in those cases alternative approaches can be used. For example for svg see: https://github.com/mhevery/ng2-svg
另一种删除我使用的组件主机的方法。
指令remove-host
//remove the host of avatar to be rendered as svg
@Directive({
selector: '[remove-host]'
})
class RemoveHost {
constructor(private el: ElementRef) {
}
//wait for the component to render completely
ngOnInit() {
var nativeElement: HTMLElement = this.el.nativeElement,
parentElement: HTMLElement = nativeElement.parentElement;
// move all children out of the element
while (nativeElement.firstChild) {
parentElement.insertBefore(nativeElement.firstChild, nativeElement);
}
// remove the empty element(the host)
parentElement.removeChild(nativeElement);
}
}
使用这个指令;
<avatar [name]="hero.name" remove-host></avatar>
在 remove-host
指令中,nativeElement
的所有子元素都插入到宿主元素之前,然后移除宿主元素。
Sample Example Gist
根据用例,可能存在一些性能问题。
与其尝试摆脱宿主元素,不如将其转换为有效的 SVG 但在其他方面不受影响:而不是您的 元素选择器
selector: "svg-rect"
及其在模板中对应的元素:
template: `...<svg-rect>...</svg-rect>...`
切换到属性选择器:
selector: "[svg-rect]"
并将该属性添加到组元素标签中:
template: `...<g svg-rect>...</g>...`
这将扩展为:
<svg height="550" width="450" x="0" y="0">
<g id="svgGroup">
<g svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</g>
<g svg-rect>
<!--template bindings={}-->
<rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect>
<!--template bindings={}-->
</g>
</g>
</svg>
这是将呈现的有效 SVG。 Plnkr
还有一种方法,我们可以从组件中取出组件的模板。
首先,我们创建组件,我们希望从浏览器渲染中删除它的标签(我们在这里不是要删除标签。)
@Component({
selector: 'tl-no-tag',
template: `
<template #tmp>
<p>{{value}}</p>
</template>`,
styleUrls: []
})
export class TlNoTagComponent {
@ViewChild('tmp') tmp: any;
value = 5;
}
然后,在另一个组件的模板中,我们写:
<tl-no-tag #source></tl-no-tag> <!-- This line can be placed anywhere -->
<template [ngTemplateOutlet]="source.tmp"></template> <!-- This line will be placed where needed -->
然后,我们在浏览器中有这样的东西:
<tl-no-tag></tl-no-tag>
<p>5</p>
因此,我们已经从 TlNoTagComponent 中取出 <p>{{value}}</p>
。 <tl-no-tag></tl-no-tag>
将继续存在,但不会阻止任何 css 或 svg-thing。
怎么样:
:host { display: contents; }
将其放入主机组件的 css(或 scss)文件中将导致组件的框不呈现。
N.B:它以前对我有用——但显然我会担心浏览器的兼容性问题,特别是如果您正在开发以支持旧版浏览器。我也很确定这并没有完全脱离 "experimental" 阶段。文档还指出这可能会导致可访问性问题。