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 文件,只要引用一次就行

相关推荐
百万蹄蹄向前冲26 分钟前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5811 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路1 小时前
GeoTools 读取影像元数据
前端
ssshooter2 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友2 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry2 小时前
Jetpack Compose 中的状态
前端
dae bal3 小时前
关于RSA和AES加密
前端·vue.js
柳杉3 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog3 小时前
低端设备加载webp ANR
前端·算法
LKAI.4 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi