在angular 2中,svg rect是一个创建rect 但由于创建了特殊的元素标记,这不会呈现rect。如果移除svg-rect标签,则会呈现rect 在Angular 1.x中,有replace:'true',它删除了编译输出中的指令标记。我们能在angular2中实现同样的功能吗?<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>
<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>
与其试图摆脱宿主元素,不如将其转换为有效的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
另一种删除我使用的组件主机的方法。
指令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
的所有子级都插入到主机之前,然后删除主机元素。
Gist示例
根据使用情况,可能存在一些性能问题
之类的东西怎么样
:host { display: contents; }
将其放入主机组件的css(或scss)文件将导致组件的长方体无法呈现。
N.B:这以前对我有用,但很明显,我会担心浏览器的兼容性,尤其是如果你正在开发支持旧浏览器的浏览器。我也很确定这并不是完全脱离了"实验"阶段。文档还指出,这可能会导致可访问性问题。
还有另一种方法可以从组件中获取组件的模板
首先,我们创建组件,我们希望从浏览器渲染中删除其标记(我们不想在这里删除标记)
@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内容。
引用Angular 1到Angular 2升级策略文档:
Angular 2中不支持替换其宿主元素的指令(替换:Angular 1中的true指令)。在许多情况下,这些指令可以升级为常规组件指令。
在某些情况下,常规组件指令将不起作用,在这些情况下,可以使用其他方法。有关svg的示例,请参阅:https://github.com/mhevery/ng2-svg