Vue学习笔记 之 Svg图标组件的实现步骤

1、安装依赖

  首先需要安装svg-sprite-loader依赖,命令如下,这在在学习的过程中,就是因为没有下载该依赖,导致图标一直无法正常显示。

npm install svg-sprite-loader --save-dev --force

2、配置svg图片处理规则

  通过使用svg-sprite-loader组件,将svg的图标文件生产雪碧图(Sprite),在vue.config.js文件中进行配置,具体如下:

//用于导入Node.js核心模块 path 的方法。path 模块提供了处理文件路径的实用工具,可以用于处理和操作文件路径字符串。
const path = require('path')
//定义了一个名为 resolve 的函数,用于将相对路径转换为绝对路径。__dirname 是 Node.js 中的一个全局变量,表示当前模块文件所在的目录的绝对路径。
function resolve(dir) {
    
    
  return path.join(__dirname, dir)
}

module.exports = {
    
    
  lintOnSave: false,
  transpileDependencies: ["vue"],
  publicPath: '/sys', // 设置上下文路径,与Tomcat或Nginx中的上下文路径保持一致
  indexPath: 'index.html', // 相对于打包路径index.html的路径
  outputDir: 'sys', // 'dist', 生产环境构建文件的目录
  productionSourceMap: true,
  devServer: {
    
    
    port: 8881,
    headers: {
    
    
      'Access-Control-Allow-Origin': '*',
    }
  },
  chainWebpack(config) {
    
    
	//覆盖默认配置中处理svg的规则
    config.module
      .rule('svg')//定义规则名称,必须为svg,为了覆盖该规则
      .exclude.add(resolve('src/components/SvgIcon'))
      .end()
	//定义处理指定目录下svg图片的规则
    config.module
      .rule('icons1')//定义规则名称,可以自定义
      .test(/\.svg$/)//表示该规则只适用于后缀为 .svg 的文件。
      .include.add(resolve('src/components/SvgIcon'))//只对这个目录下的SVG文件应用该规则。
      .end()
      .use('svg-sprite-loader')// 指定了使用 svg-sprite-loader 这个loader来处理满足该规则的SVG文件。
      .loader('svg-sprite-loader')//指定了要使用的loader为 svg-sprite-loader。
      .options({
    
    //对 svg-sprite-loader 的配置选项,通过 symbolId 可以设置每个图标的标识符,这里使用 icon-[name] 表示使用图标文件的名称作为标识符。
        symbolId: 'icon-[name]'
      })
      .end()
  }
};

雪碧图(Sprite)是一种将多个小图标或图片合并到一个大图中的技术。通过将多个图标放置在同一张图上,并通过CSS的background-position属性来控制显示不同的图标位置,可以减少网络请求次数,提高页面加载速度和性能。

3、定义svg-icon组件

  svg-icon组件包括了svg文件(svg图片)、index.vue和index.js三部分内容。其中,svg文件,主要包括了各个图标对应的svg文件,上述vue.config.js文件中的配置,就是将该文件下的文件生成雪碧图;index.vue用来定义图标的vue组件;index.js实现了svg-icon组件的注册。具体实现如下:

  index.vue页面,代码如下:

<template>
  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script>
import {
      
       isExternal } from '@/utils/validate'

export default {
      
      
  name: 'SvgIcon',
  props: {
      
      
    iconClass: {
      
      
      type: String,
      required: true
    },
    className: {
      
      
      type: String,
      default: ''
    }
  },
  computed: {
      
      
    isExternal() {
      
      
      return isExternal(this.iconClass)
    },
    iconName() {
      
      
      return `#icon-${ 
        this.iconClass}`
    },
    svgClass() {
      
      
      if (this.className) {
      
      
        return 'svg-icon ' + this.className
      } else {
      
      
        return 'svg-icon'
      }
    },
    styleExternalIcon() {
      
      
      return {
      
      
        mask: `url(${ 
        this.iconClass}) no-repeat 50% 50%`,
        '-webkit-mask': `url(${ 
        this.iconClass}) no-repeat 50% 50%`
      }
    }
  }
}
</script>

<style scoped>
.svg-icon {
      
      
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

.svg-external-icon {
      
      
  background-color: currentColor;
  mask-size: cover!important;
  display: inline-block;
}
</style>

  index.js文件,代码如下:

import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component

// 注册
Vue.component('svg-icon', SvgIcon)
//在当前文件所在目录下的 ./svg 目录中查找所有以 .svg 结尾的文件,并将匹配的文件创建一个模块上下文
const req = require.context('./svg', false, /\.svg$/)
//将模块上下文中的所有模块导入,并注册为SvgIcon组件的子组件。
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

  处理后的数据:
在这里插入图片描述

4、svg图标使用和展示

  这里实现了一个展示全部svg图标的页面,包括了svg-icons.js文件和index.vue文件,其中,svg-icons.js主要读取所有的svg图标的名称;index.vue定义了展示图标的页面。

  svg-icons.js代码实现如下,类似上述index.js文件,读取文件目录,获取文件名称:

const req = require.context('../SvgIcon/svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys()

const re = /\.\/(.*)\.svg/

const svgIcons = requireAll(req).map(i => {
    
    
  return i.match(re)[1]
})
console.log(svgIcons);
export default svgIcons

在这里插入图片描述

  index.vue页面代码实现如下:

<template>
  <div class="icons-container">
    <el-tabs type="border-card">
      <el-tab-pane label="Icons">
        <div v-for="item of svgIcons" :key="item">
          <el-tooltip placement="top">
            <div slot="content">
              {
   
   { generateIconCode(item) }}
            </div>
            <div class="icon-item">
              <svg-icon :icon-class="item" class-name="disabled" />
              <span>{
   
   { item }}</span>
            </div>
          </el-tooltip>
        </div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script>
import svgIcons from './svg-icons'

export default {
      
      
  name: 'Icons',
  data() {
      
      
    return {
      
      
      svgIcons
    }
  },
  methods: {
      
      
    generateIconCode(symbol) {
      
      
      return `<svg-icon icon-class="${ 
        symbol}" />`
    }
  }
}
</script>

<style lang="scss" scoped>
.icons-container {
      
      
  margin: 10px 20px 0;
  overflow: hidden;
  .icon-item {
      
      
    margin: 20px;
    height: 85px;
    text-align: center;
    width: 100px;
    float: left;
    font-size: 30px;
    color: #24292e;
    cursor: pointer;
  }
  span {
      
      
    display: block;
    font-size: 16px;
    margin-top: 10px;
  }
  .disabled {
      
      
    pointer-events: none;
  }
}
</style>

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/hou_ge/article/details/131716824