• Vue3:自定义图标选择器(包含 SVG 图标封装)



    效果预览:
    在这里插入图片描述

    一、准备工作(在 Vue3 中使用 SVG

    本文参考:https://blog.csdn.net/houtengyang/article/details/129043100

    1. 安装插件

      npm i vite-plugin-svg-icons
      
      • 1
    2. 配置插件

      1. 修改 vite.config.js

        import {resolve} from 'path'
        import {createSvgIconsPlugin} from 'vite-plugin-svg-icons';
        
        export default defineConfig({
            plugins: [
                vue(),
                createSvgIconsPlugin({
                    iconDirs: [resolve(process.cwd(), 'public')], // svg 文件存放位置
                    symbolId: 'icon-[name]', // 指定symbolId格式
                }),
            ],
        })
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12

        注意:我的 svg 存放路径是根目录下的 ./public,多数情况下放在 ./src/assets

      2. 修改 main.js,增加一行代码。

        import 'virtual:svg-icons-register'
        
        • 1
    3. 使用示例

          <svg aria-hidden="true" style="width: 14px; height: 14px">
              <use :href="`#icon-${menu.icon}`" />
          svg>
      
      • 1
      • 2
      • 3

    二、封装 SVG

    将上述使用示例封装为组件。

    1. ./src/components 下创建 Icon.vue

      <script setup>
      const props = defineProps({
          prefix: {type: String, default: 'icon'},
          name: {type: String, required: true},
          color: {type: String},
          size: {type: String, default: '1em'}
      });
      
      const symbolId = computed(() => `#${props.prefix}-${props.name}`);
      </script>
      
      <template>
          <svg aria-hidden="true" class="svg-icon" :style="'vertical-align:middle;width:' + size + ';height:' + size">
              <use :href="symbolId" :fill="color"/>
          </svg>
      </template>
      
      <style scoped>
      .svg-icon {
          overflow: hidden;
          fill: currentColor;
      }
      </style>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

      svg 样式里添加了 vertical-align:middle

    2. 使用示例

      <Icon :name="vite">Icon>
      
      • 1

    三、封装图标选择器

    1. ./src/components 下创建 IconSelect.vue

      <script setup>
      import Icon from "@/components/Icon.vue";
      
      const props = defineProps({
          modelValue: {type: String, default: ''},
      });
      
      const value = ref(props.modelValue)
      const icons = [];
      const modules = import.meta.glob('../../public/**/*.svg');
      for (const path in modules) {
          const name = path.split('public/')[1].split('.svg')[0];
          icons.push(name);
      }
      
      const emits = defineEmits(['update:modelValue']);
      const change = (name) => {
          emits('update:modelValue', name)
      }
      </script>
      
      <template>
          <el-select v-model="value" @change="change" filterable clearable placeholder="Select Icon">
              <el-option v-for="item in icons" :key="item" :label="item" :value="item">
                  <span style="float: left">
                      <Icon :name="item" size="30px"></Icon>
                  </span>
                  <span style="float: right;color: var(--el-text-color-secondary);font-size: 13px;">
                      {{ item }}
                  </span>
              </el-option>
          </el-select>
          <Icon :name="value" size="32px" style="padding-left: 10px"></Icon>
      </template>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34

      import.meta.glob('../../public/**/*.svg') 用于获取 ./public 路径下各个层级的 .svg 文件。

    2. 使用示例(在表单中使用):

      <el-form-item label="Icon">
          <IconSelect v-model="obj.icon">IconSelect>
      el-form-item>
      
      • 1
      • 2
      • 3

    在这里插入图片描述

    四、Demo

    <script setup>
    import IconSelect from "@/components/IconSelect.vue";
    import Icon from "@/components/Icon.vue";
    
    const symbol = ref('')
    </script>
    
    <template>
        {{ symbol }}
        <Icon :name="symbol" size="32px" style="padding-left: 10px"></Icon>
        <br/>
        <IconSelect v-model="symbol"/>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

  • 相关阅读:
    【办公类-16-05-01】“大班游戏活动室排班表——班主任版21周”(python 排班表系列)
    微信公众号添加Word文档附件教程_公众号添加Excel、PDF、PPT、Zip等附件教程
    项目沟通和干系人管理
    Rust-FFI复杂参数传递处理方式2--字符和字符串类型
    小白学安全-KunLun-M静态白盒扫描工具
    wind量化接口owkey的缩短特点是什么?
    Three.js--》实现3d地球模型展示
    Elasticsearch安装
    BL200Pro分布式IO模块如何配置WEB端
    CSS层叠样式表
  • 原文地址:https://blog.csdn.net/KissedBySnow/article/details/134293926