美文网首页vuereact & vue & angular
Vue-CLI中使用svg icon图标

Vue-CLI中使用svg icon图标

作者: 硅谷干货 | 来源:发表于2022-06-17 23:11 被阅读0次

    背景

    最近几个项目常用到svg图片,往往步骤还不少,每次都要上网查一遍怎么配置,不如自己走一遍,深入理解下,记录下来。

    配置步骤

    在Vue-CLI中配置svg的icon,可以参照下面的步骤。

    1. 需要用到雪碧图的loader,解析svg。
    npm install svg-sprite-loader --save-dev
    复制代码
    
    1. 配置vue.config.js,加入sprite-loader的解析。
    module.exports = {
      chainWebpack: config => {
        // 原svg规则覆盖了所有的svg图标,需要先将自己的svg排除,以应用新的sprite规则
        // src/assets/icons是我们将要存放svg的目录
        config.module
          .rule('svg')
          .exclude.add(path.join(__dirname, 'src/assets/icons')) // 排除自定义svg目录
          .end()
        config.module
          .rule('icons') // 新规则
          .test(/\.svg$/)
          .include.add(path.join(__dirname, 'src/assets/icons')) // 新规则应用于我们存放svg的目录
          .end()
          .use('svg-sprite-loader') // 用sprite-loader接卸
          .loader('svg-sprite-loader')
          .options({
            symbolId: 'icon-[name]'
          })
          .end()
      }
    }
    复制代码
    
    image.png
    1. 创建全局SvgIcon组件,用于页面显示svg icon。组件位置:src/components/SvgIcon.vue
    <template>
        <svg class="svg-icon" aria-hidden="true">
            <use :xlink:href="`#icon-${name}`" />
        </svg>
    </template>
    
    <script>
    export default {
      name: 'SvgIcon',
      props: {
        name: { // svg文件名称
          type: String,
          required: true
        }
      }
    }
    </script>
    
    <style scoped>
    .svg-icon {
      width: 1em;
      height: 1em;
      vertical-align: -0.15em;
      fill: currentColor;
      overflow: hidden;
    }
    </style>
    
    复制代码
    
    1. 在main.js中,全局引入SvgIcon组件,以及加载所有的svg图标。
    import Vue from 'vue'
    import SvgIcon from '@/components/SvgIcon'// svg组件
    
    // 1. 全局注册SvgIcon组件
    Vue.component('svg-icon', SvgIcon)
    // 2. 载入所有svg icon
    const requireContext = require.context('./assets/icons', false, /\.svg$/)
    requireContext.keys().forEach(requireContext)
    复制代码
    
    1. 将svg放入src/asset/icons目录下
    image.png
    1. 在页面中引用,即大功告成。
    <svg-icon name="book" /> <!-- name就是svg图标文件的名称 -->
    复制代码
    

    后记

    看了好多篇关于svg的配置,往往拿来主义,直接用,有些不合理的地方也一传十,十传百。

    1. 引入svg icon

    原版是这样:

    const req = require.context('./svg', false, /\.svg$/)
    const requireAll = requireContext => requireContext.keys().map(requireContext)
    requireAll(req)
    复制代码
    

    我看来看去,最后不就是执行这一句么requireContext => requireContext.keys().map(requireContext),为什么要拐那么多弯呢?而且最终目的只要把资源require进来就行了,用map也没意义,于是我修改成:

    const requireContext = require.context('./assets/icons', false, /\.svg$/)
    requireContext.keys().forEach(requireContext)
    复制代码
    

    关于requreiContext

    a) require.context()函数功能为加载多个资源,requreiContextrequire.context()的返回结果,是一个函数,打印出来的代码是这样:

    function webpackContext(req) {
      var id = webpackContextResolve(req);
      return __webpack_require__(id);
    }
    复制代码
    

    这个函数的作用就是根据名称加载资源,返回资源对象,如{default:{...}}.

    b) requreiContext的原型有3个属性,id、keys、resolve, 后两者为函数。keys返回所有资源的文件名列表,resolve返回资源的相对项目的完整路径。打印原型requreiContext.prototype得到如下结果:

    image.png

    打印requireContext.keys()得到如下结果:

    2. SvgIcon组件

    网上大多文章用的是这个版本:

    <template>
      <svg :class="svgClass" aria-hidden="true">
        <use :xlink:href="iconName" />
      </svg>
    </template>
    
    <script>
    export default {
      name: 'SvgIcon',
      props: {
        iconClass: {
          type: String,
          required: true
        },
        className: {
          type: String,
          default: ''
        }
      },
      computed: {
        iconName() {
          return `#icon-${this.iconClass}`
        },
        svgClass() {
          if (this.className) {
            return 'svg-icon ' + this.className
          } else {
            return 'svg-icon'
          }
        }
      }
    }
    </script>
    
    <style scoped>
    .svg-icon {
      width: 1em;
      height: 1em;
      vertical-align: -0.15em;
      fill: currentColor;
      overflow: hidden;
    }
    </style>
    复制代码
    

    a)发现className属性和svgClass完全没必要,引用svg-icon组件时,直接加class属性就行,会自动合并,何必画蛇添足。像这样就可以了:

    <svg-icon name="book" class="myicon" />
    复制代码
    

    b)iconClass不好理解,直接取名name更简洁清晰;计算属性iconName也是完全没太大必要,毕竟组件定下了,name属性就是不变的。

    修改后就变成简洁版本:

    <template>
        <svg class="svg-icon" aria-hidden="true">
            <use :xlink:href="`#icon-${name}`" />
        </svg>
    </template>
    
    <script>
    export default {
      name: 'SvgIcon',
      props: {
        name: {
          type: String,
          required: true
        }
      }
    }
    </script>
    
    <style scoped>
    .svg-icon {
      width: 1em;
      height: 1em;
      vertical-align: -0.15em;
      fill: currentColor;
      overflow: hidden;
    }
    </style>
    复制代码
    

    当然,也许有性能或者其他什么方面的考量,目前我没看出加那些的必要。

    3. 获取svg icon

    我常去的网站是这个,阿里巴巴矢量图标库,资源很丰富。

    相关文章

      网友评论

        本文标题:Vue-CLI中使用svg icon图标

        本文链接:https://www.haomeiwen.com/subject/kftkvrtx.html