iconfont的一个坑(使用symbol方式引入多个icon导致覆盖)

问题发生

最近写项目的时候想用几个 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 文件,只要引用一次就行

相关推荐
你挚爱的强哥18 分钟前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js