sprite的概念

sprite的概念最早是图片上的sprite。
一个页面的请求资源中图片 img 占了大部分,所以为了优化有了image sprite 就是所谓的雪碧图,就是将多个图片合成一个图片,然后利用 css 的 background-position 定位显示不同的 icon 图标。

如何使用iconfont字体图标?

下面展示的是使用unicode的方式。

<style>
        @font-face {
            font-family: 'good';
            src: url('./iconfont/iconfont.ttf?t=1644902967906') format('truetype');
        }
        .good {
            font-family: "good" !important;
            font-size: 16px;
            font-style: normal;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
            color: red;
        }   
    </style>
</head>

<body>
    <span class="good">&#xe867;</span>
</body>

优点

兼容性最好,支持ie6+

缺点

unicode的书写不直观,语意不明确。光看&#xe867;这个unicode你完全不知道它代表的是什么意思。所以就引入了font-class,在demo_index.html中有介绍如何使用。

如何使用svg图标(svg-icon)?

使用方法

第一步

下载iconfont购物车下面生成的代码,在使用的页面引入 ./iconfont.js
<script type="text/javaScript" src="./iconfont/iconfont.js"></script>

第二步

加入通用css代码(引入一次就行):

<style type="text/css">
    .icon {
       width: 1em; height: 1em;
       vertical-align: -0.15em;
       fill: currentColor;
       overflow: hidden;
    }
</style>

第三步

挑选相应图标并获取类名(在下载完的代码里面有个demo_index.html可以看到id),应用于页面:
<use xlink:href="#icon-xxx"></use>

    <!-- 通过#icon-id就可以选取 -->
    <svg class="icon" aria-hidden="true">
        <use xlink:href="#icon-ditu" class="redColor"></use>
    </svg>
    <svg class="icon" aria-hidden="true">
        <use xlink:href="#icon-ditu"></use>
    </svg>

使用成功!
在这里插入图片描述

使用svg-icon的好处

再也不用发送woff|eot|ttf| 这些很多个字体库请求了,所有的svg都可以内联在html内。

基于svg-icon图标创建icon-component 组件

//components/SvgIcon/index.vue
<template>
  <svg class="svg-icon" aria-hidden="true">
    <!-- iconName是外界传入的icon名通过计算属性加工之后得来的 -->
    <use :xlink:href="iconName"></use>
  </svg>
</template>

<script setup>
//  1. 在script setup中声明的变量(包括变量,函数声明,以及 import 引入的内容)
//  可以在模板中直接使用
//  2. 该脚本会被预处理并作为组件的 setup() 函数使用,也就是说它会在每个组件实例中执行
//  3. 无法指定当前组件的名字,会自动以文件名为主,省去了 name 属性
import { defineProps, computed } from 'vue'
//  defineProps 接收与 props 选项相同的值
const props = defineProps({
  icon: {
    type: String,
    required: true
  }
})
//  对外界传入的icon进行加工变成#icon-iconName
const iconName = computed(() => {
  return `#icon-${props.icon}`
})
</script>

<style lang="scss" scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  /* 填充色 */
  fill: currentColor;
  overflow: hidden;
}
</style>
//引入svg组件
import SvgIcon from '@/components/SvgIcon'

//全局注册svg-icon
Vue.component('svg-icon', SvgIcon)

//在代码中使用
<svg-icon icon="password" />

改造icon-component 组件——生成svg-sprite

上面组件存在一个问题就是:就是现在所有的 svg-sprite都需要通过 iconfont 的 iconfont.js 生成,也就是说如果要加入一个图标,就必须重新下载一次iconfont.js文件,然后替换掉原先的,这会非常麻烦。
其次它做不到按需加载,不能根据我们使用了那些 svg 从而动态地生成 svg-sprite。

使用 svg-sprite

所以我们打算自己制作 svg-sprite 。
使用工具:svg-sprite-loader (它是一个 webpack loader ,可以将多个 svg 打包成 svg-sprite )

//vue.config.js
chainWebpack(config) {
    // config 为 webpack 配置对象
    // config.module 表示创建一个具名规则,以后用来修改规则
    config.module
    //  vue-cli默认情况下会使用 url-loader 对svg进行处理,会将它放在/img 目录下
    //  所以这个规则用于忽略这个文件夹,避免与雪碧图产生冲突
      // 规则的名字
      .rule('svg')
      // 忽略
      .exclude.add(resolve('src/icons'))
      // 结束
      .end()
    // config.module 表示创建一个具名规则,以后用来修改规则
    config.module
      // 规则
      .rule('icons')
      // 正则,解析 .svg 格式文件
      .test(/\.svg$/)
      // 解析的文件
      .include.add(resolve('src/icons'))
      // 结束
      .end()
      // 新增了一个解析的loader
      .use('svg-sprite-loader')
      // 具体的loader
      .loader('svg-sprite-loader')
      // loader 的配置
      .options({
        symbolId: 'icon-[name]'
      })
      // 结束
      .end()
 }

这样子之后,就能按需引入图标

import '@/src/icons/xx.svg; //引入图标
<svg><use xlink:href="#xx" /></svg>  //使用图标

但是这又有一个问题,如果我要引入很多个图标,就需要import很多次,不够方便,所以下面引出自动导入。

自动导入所有svg-icon

创建一个专门放置图标 icon 的文件夹如:@/src/icons,将所有 icon 放在这个文件夹下的svg文件夹。 之后我们就要使用到 webpack 的 require.context。

//@/src/icons/index.js
import SvgIcon from '@/components/SvgIcon'
// 使用require.context api,它会遍历svg文件夹中的以.svg结尾的文件,然后自动导入,
// false表示不遍历子目录
const svgRequired = require.context('./svg', false, /\.svg$/)
// require.context返回的是一个函数,keys是这个函数的一个属性
// keys {Function} -返回匹配成功模块的名字组成的数组
svgRequired.keys().forEach((item) => svgRequired(item))
export default (app) => {
  app.component('svg-icon', SvgIcon)
}

在main.js中全局注册组件

//main.js
import SvgIcon from '@/icons'
const app = createApp(App)
SvgIcon(app)

之后我们增删改图标直接在@/src/icons/svg修改就好了下,就会自动生成 svg symbol了。在页面中就可以自动使用了。

参考学习

学习资料

Logo

前往低代码交流专区

更多推荐