问题发生
最近写项目的时候想用几个 icon,遂上 iconfont 寻找
在下载下来的 demo 文件中,我们可以看到官方推荐我们使用 Symbol 引用方式
于是我就是用了这种方式,但是当我引入第二个 icon 的时候,我发现我第一个 icon 不显示了
demo代码如下:
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
</head>
<body>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-github"></use>
</svg>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-juejin"></use>
</svg>
<script src="./src/assets/github/iconfont.js"></script>
<script src="./src/assets/juejin/iconfont.js"></script>
</body>
</html>
显示结果:
可以看到只显示了掘金的 icon,没有 github 的 icon
解决
经过一番排查,我发现可能发生了覆盖,因为只有后导入的标签进行了显示。
use 的使用
这里 use 标签的在 SVG 文档内取得目标节点,并在别的地方复制它们,
通过它的 xlink 属性,实现了和 js 文件(也就是我们引入的文件)中 symbol 标签的 id 连结。
所以显示什么文件由这里的xlink:href
后的 id 决定。
那照这么说,既然由 id 区分,怎么会出现覆盖冲突呢?
Js 文件
我们前往导入的 js 文件中,观察/github/iconfont.js
和/juejin/iconfont.js
的区别
可以看到这里先是在 window 上定义了一个属性_iconfont_svg_string_
然后立即执行后面的函数并把 windows 传入作为 n
然后在该函数中等待 document 加载好后会调用到赋值的函数 o,这里函数 o 赋值也是通过window._iconfont_svg_string_
属性得到的
javascript
(window._iconfont_svg_string_ =
'<svg><symbol id="icon-github" viewBox="0 0 1024 1024"><path d="M511.957333 21.333333C241.024 21.333333 21.333333 240.981333 21.333333 512c0 216.832 140.544 400.725333 335.573334 465.664 24.490667 4.394667 32.256-10.069333 32.256-23.082667 0-11.690667 0.256-44.245333 0-85.205333-136.448 29.610667-164.736-64.64-164.736-64.64-22.314667-56.704-54.4-71.765333-54.4-71.765333-44.586667-30.464 3.285333-29.824 3.285333-29.824 49.194667 3.413333 75.178667 50.517333 75.178667 50.517333 43.776 75.008 114.816 53.333333 142.762666 40.789333 4.522667-31.658667 17.152-53.376 31.189334-65.536-108.970667-12.458667-223.488-54.485333-223.488-242.602666 0-53.546667 19.114667-97.322667 50.517333-131.669334-5.034667-12.330667-21.930667-62.293333 4.778667-129.834666 0 0 41.258667-13.184 134.912 50.346666a469.802667 469.802667 0 0 1 122.88-16.554666c41.642667 0.213333 83.626667 5.632 122.88 16.554666 93.653333-63.488 134.784-50.346667 134.784-50.346666 26.752 67.541333 9.898667 117.504 4.864 129.834666 31.402667 34.346667 50.474667 78.122667 50.474666 131.669334 0 188.586667-114.730667 230.016-224.042666 242.090666 17.578667 15.232 33.578667 44.672 33.578666 90.453334v135.850666c0 13.141333 7.936 27.605333 32.853334 22.869334C862.250667 912.597333 1002.666667 728.746667 1002.666667 512 1002.666667 240.981333 783.018667 21.333333 511.957333 21.333333z" ></path></symbol></svg>'),
(function (n) {
//...省略
(o = function () {
var t,
e = document.createElement("div");
(e.innerHTML = n._iconfont_svg_string_),
(e = e.getElementsByTagName("svg")[0]) &&
(e.setAttribute("aria-hidden", "true"),
(e.style.position = "absolute"),
(e.style.width = 0),
(e.style.height = 0),
(e.style.overflow = "hidden"),
(e = e),
(t = document.body).firstChild
? a(e, t.firstChild)
: t.appendChild(e));
}),
document.addEventListener
? ~["complete", "loaded", "interactive"].indexOf(document.readyState)
? setTimeout(o, 0)
: ((i = function () {
document.removeEventListener("DOMContentLoaded", i, !1), o();
}),
document.addEventListener("DOMContentLoaded", i, !1))
: document.attachEvent &&
((c = o),
(d = n.document),
(s = !1),
r(),
(d.onreadystatechange = function () {
"complete" == d.readyState &&
((d.onreadystatechange = null), l());
}));
}
//...省略
})(window);
而另一个 js 文件类似,除了 symbol 的 id 不一样之外
我们可以通过一个更简单的函数来模拟这两个 js 文件一起使用的情况:
lua
let a = {};
(a.status = "unhappy"),
(function (n) {
setTimeout(function () {
console.log(n.status);
}, 0);
})(a);
(a.status = "happy"),
(function (n) {
setTimeout(function () {
console.log(n.status);
}, 0);
})(a);
答案显然是输出两个 happy,而我们在引入两个js文件的时候,window上的属性也会出现相同的情况。
解决方法
1.修改 js 文件中的_iconfont_svg_string_
属性,防止两个重合
2.在 iconfont 里不要分开引用,把要用的图标同时放购物车里再下载,这样下载下来的图标声明都在同一个 js 文件,只要引用一次就行