WebKit策略:<foreignObject>可用于绘制svg中的html标签,但与<use>搭配不生效

在<svg>里面可以利用<foreignObject>绘制html标签 , 原本是我在iconfont采用Font class方式引入svg的无奈之举 。
起初的设计是所有icon先在<defs>中先渲染 , 以达到icon复用的效果 , icon采用Symbol方式引入svg感觉也是比较合适的 , 比较规范的 。
<template><defs><g v-for="item in list" :key="item._id" :id="'icon-' + item._id"><svg aria-hidden="true" width="16" height="16" x="0" y="0"><use :xlink:href="'#' + item.icon"></use></svg></g></defs></template><script>export default {data() {return {list: [],};},};</script>然后再需要用到的地方用<use :xlink:href="'#icon-' + id" />克隆下来 , 感觉很完美 。
但是理想很丰满 , 现实很骨感 。由于某些功能会被影响到 , 不能使用Symbol方式引入 , 最后只能选择Font class引入svg 。于是代码变为了下列
<template><defs><g v-for="item in list" :key="item._id" :id="'icon-' + item._id"><foreignObject width="16" height="16" x="16" y="16"><div xmlns="http://www.w3.org/1999/xhtml"><span class="iconfont" :class="item.icon"></span></div></foreignObject></g></defs></template><script>export default {data() {return {list: [],};},};</script>但是在需要的地方使用<use :xlink:href="'#icon-' + id" />克隆下来 , 会发现在谷歌浏览器上却完全显示不出<span>标签的内容 , 即不显示iconfont图标 。
刚开始 , 我以为是不能在<defs>标签中使用<foreignObject>标签 , 于是我就去查看了SVG规范 , 传送门:https://www.w3.org/TR/SVG/struct.html#DefsElement , SVG规范是支持这种写法的 。打开F12 , 查看<defs>标签下的dom结构 , 也可以看到<foreignObject>标签其实是有生成的 , 也是佐证了这一点 。

WebKit策略:&lt;foreignObject&gt;可用于绘制svg中的html标签,但与&lt;use&gt;搭配不生效

文章插图
但是查看引用<use>标签的地方 , 就没有生成对应的<foreignObject>标签 , 我查看SVG规范文档并没有提到<use>标签不能与<foreignObject>标签共同使用的限制 。最后我打开了github , 在w3c的【SVG工作组规范】项目下寻找答案 , 传送门:https://github.com/w3c/svgwg , 最后找到了一个讨论:https://github.com/w3c/svgwg/issues/511 。这位程序员在讨论中说除了 Gecko 之外的所有浏览器都限制<svg:use>元素中的<foreignObject> , 他在思考为什么Gecko之类的浏览器允许这么做 。
WebKit策略:&lt;foreignObject&gt;可用于绘制svg中的html标签,但与&lt;use&gt;搭配不生效

文章插图
这下就有点头绪了 , 原来是浏览器内核原因 。那简单 , 我们找个Gecko内核的浏览器验证下就知道了 , Gecko内核最出名的就是FireFox浏览器(火狐浏览器)了 。其实我的电脑也装了火狐浏览器 , 但是由于我开发一直用的是谷歌浏览器 , 确实也是好久好久没打开火狐了 , 放着吃灰 , 这次也确实没想到可能是浏览器本身的问题 。打开火狐浏览器 , 果然能显示<span>标签的内容 , 即显示了iconfont图标 。
WebKit策略:&lt;foreignObject&gt;可用于绘制svg中的html标签,但与&lt;use&gt;搭配不生效

文章插图
不过为什么会出现这样的情况呢 , 另一个叫Dirk Schulze的程序员表示:出于复杂性的原因 , WebKit不允许引用foreignObject 。我们没有时间查看所有影响(包括安全影响) , 如果内容是基于HTML的 , 那么对foreignObject的支持永远不会很好 。(Blink修复了后半部分)

经验总结扩展阅读