• vue2+webpack/vue3+vite 封装svg组件总结笔记


    一、vue2+webpack

    1.npm安装依赖包

    npm i svg-sprite-loader
    

    package.json

    "svg-sprite-loader": "^5.0.0"
    

    main.js

    import { registerSvgIconComp } from '@/plugins/registerSvgIcon'
    registerSvgIconComp(app)
    

    vue.config.js文件

    module.exports = {
      publicPath: '/',
      // 打包输出
      outputDir: 'dist',
    // 链式webpack配置
      chainWebpack: config => {
        // 设置 svg-sprite-loader
        config.module
          .rule('svg')
          .exclude.add(resolve('src/icons'))
          .end()
        config.module
          .rule('icons')
          .test(/\.svg$/)
          .include.add(resolve('src/icons'))
          .end()
          .use('svg-sprite-loader')
          .loader('svg-sprite-loader')
          .options({
            symbolId: 'icon-[name]'
          })
          .end()
      },
     }
    '
    运行

    2.组件封装

    /plugins/registerSvgIcon.js

    // svg-icon
    import SvgIcon from '@/components/SvgIcon'
    
    const req = require.context('@/icons/svg', false, /\.svg$/)
    const requireAll = requireContext => requireContext.keys().map(requireContext)
    requireAll(req)
    
    export function registerSvgIconComp(app) {
      app.component('SvgIcon', SvgIcon)
    }
    
    

    /components/SvgIcon

    <template>
      <view v-if="isExternalIcon" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-bind="$attrs"></view>
      <svg v-else :class="svgClass" aria-hidden="true" v-bind="$attrs">
        <use :xlink:href="iconName" />
      </svg>
    </template>
    
    <script>
    import { isExternal } from '@/utils/validate'
    import { computed } from 'vue'
    
    export default {
      name: 'SvgIcon',
      props: {
        iconClass: {
          type: String,
          required: true,
        },
        className: {
          type: String,
          default: '',
        },
      },
      setup(props) {
        console.log('props.iconClass :>> ', props.iconClass)
        console.log('props.className', props.className)
        const isExternalIcon = computed(() => isExternal(props.iconClass))
        const iconName = computed(() => `#icon-${props.iconClass}`)
        const svgClass = computed(() => {
          if (props.className) {
            return 'svg-icon ' + props.className
          } else {
            return 'svg-icon'
          }
        })
        const styleExternalIcon = computed(() => {
          return {
            mask: `url(${props.iconClass}) no-repeat 50% 50%`,
            '-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`,
          }
        })
    
        return {
          isExternalIcon,
          iconName,
          svgClass,
          styleExternalIcon,
        }
      },
    }
    </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>
    

    3.组件调用

     <div>
     	<svg-icon icon-class="ic-tips" /> &nbsp;验证码
     </div>
    

    二、vue3+vite

    1.npm安装依赖包(这是npm截止笔记时间最新包,我用的不是最新的)

    npm i vite-plugin-svg-icons@0.6.0-beta.1
    

    package.json

    "vite-plugin-svg-icons": "^2.0.1"
    

    2.main.js配置

    // svg-icon
    import 'vite-plugin-svg-icons/register'// 看哪个管用
    // import 'virtual:svg-icons-register' // 看哪个管用
    //组件全局调用
    import { registerSvgIconComp } from '@/plugins/registerSvgIcon'
    
    registerSvgIconComp(app)
    
    

    3.组件封装

    /plugins/registerSvgIcon.js

    // svg-icon
    import SvgIcon from '@/components/SvgIcon'
    
    const files = import.meta.globEager('../static/icons/svg/*.svg') // vite
    
    const modules = {}
    
    const requireAll = (files) => {
      for (const key in files) {
        if (Object.prototype.hasOwnProperty.call(files, key)) {
          modules[key.replace(/(\.\/|\.svg)/g, '')] = files[key].default
        }
      }
    }
    requireAll(files)
    
    export function registerSvgIconComp(app) {
      app.component('SvgIcon', SvgIcon)
    }
    
    

    /components/SvgIcon.vue

    <template>
      <view v-if="isExternalIcon" :style="styleExternalIcon" class="svg-external-icon svg-icon"></view>
      <svg v-else :class="svgClass" aria-hidden="true">
        <use :xlink:href="iconName" />
      </svg>
    </template>
    
    <script>
    import { isExternal } from '@/utils/validate'
    import { computed } from 'vue'
    
    export default {
      name: 'SvgIcon',
      props: {
        iconClass: {
          type: String,
          required: true,
        },
        className: {
          type: String,
          default: '',
        },
      },
      setup(props) {
        const isExternalIcon = computed(() => isExternal(props.iconClass))
        const iconName = computed(() => `#icon-${props.iconClass}`)
        const svgClass = computed(() => {
          if (props.className) {
            return 'svg-icon ' + props.className
          } else {
            return 'svg-icon'
          }
        })
        const styleExternalIcon = computed(() => {
          return {
            mask: `url(${props.iconClass}) no-repeat 50% 50%`,
            '-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`,
          }
        })
    
        return {
          isExternalIcon,
          iconName,
          svgClass,
          styleExternalIcon,
        }
      },
    }
    </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>
    

    4.组件调用

     <div>
     	<svg-icon icon-class="ic-tips" /> &nbsp;验证码
     </div>
    

    注意:uniapp转微信小程序失败:Error: 暂不支持 v-bind=“” 用法
    原因就是字面意思,只能老老实实使用props接受父组件传参,一个个再传进去。包括父组件得行内样式style,反正就是不能偷懒。

  • 相关阅读:
    Go语言超全详解(入门级)
    解决VUE报错GET http://127.0.0.1:5500/favicon.ico 404 (Not Found)
    YAYA LIVE CTO 唐鸿斌:真正本地化,要让产品没有「产地」属性
    Java的环境配置
    rsync + inotify 同步数据
    案例分析-金融业网络安全攻防
    Debian
    基于pythonGUI的图形绘图及图元编辑系统
    kanzi案例Coin
    一个简单的查询学生信息的接口测试
  • 原文地址:https://blog.csdn.net/Winsom1/article/details/127102649