qq_42724979 2024-05-09 12:40 采纳率: 33.3%
浏览 6
已结题

Vite 打包的 Vue3 组件库,图标无法显示

我准备基于 Vue3 技术写一个富文本编辑器组件,并以组件库的形式打包上传 NPM 仓库,且有其他 Vue3 的项目下载并使用

以下是富文本编辑器的一个子组件,它是富文本编辑器的工具栏(Toolbar)部分,这部分功能为将工具栏的每个工具项通过循环的方式显示在界面,每个工具项都有专属的 ICON 图标(图标是:SVG),代码如下:

注意:为聚焦问题,将代码进行了简化,代码中的 ... 处指代省略代码部分

<template>
  <div id="editorMenu" class="editor-menu">
    <div
      ref="menuItems"
      v-for="(name, index) in menu"
      ...
    >
      <template>
        <button ...>
          <!-- 标题 -->
          <template v-if="name === 'heading'">
            '正文'
            <svg class="icon arrow-down">
              <use :xlink:href="`${remixicon}arrow-down`"></use>
            </svg>
          </template>
        </button>
      </template>
    <div>
    ...
  <div>
</template>

<script lang="ts" setup>
import remixicons from '@/assets/remixicon.symbol.svg';

const remixicon = computed(() => `${remixicons}#`);

const menu = computed(() => ['heading']);
...
</script>

以下为 SVG 图标文件,文件全路径为:src/assets/remixicon.symbol.svg,代码如下:

<?xml version="1.0" encoding="utf-8"?>

<svg xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="0" height="0" style="display:none;">
  <symbol id="arrow-down" viewBox="0 0 24 24">
    <path fill="none" d="M0 0h24v24H0z"/>
    <path d="M12 15l-4.243-4.243 1.415-1.414L12 12.172l2.828-2.829 1.415 1.414z"/>
  </symbol>
</svg>

我采用的打包工具是 Vite,且 vite.config.js 配置如下:

import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import { resolve } from 'path';
import { defineConfig, loadEnv } from 'vite';
import autoprefixer from 'autoprefixer';
import tailwindcss from 'tailwindcss';
import dts from 'vite-plugin-dts';

export default defineConfig(({ mode }) => {
  process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };

  return {
    resolve: {
      alias: {
        '@': resolve(__dirname, 'src/'),
      },
    },

    plugins: [
      vueJsx({ isCustomElement: (tag) => tag === 'iconpark-icon', include: ['../**/*.tsx'] }),
      vue({
        template: {
          compilerOptions: {
            isCustomElement: (tag) => {
              return tag === 'iconpark-icon';
            },
          },
        },
        customElement: 'iconpark-icon',
      }),
      dts({
        outDir: './dist/types',
      }),
    ],

    css: {
      postcss: {
        plugins: [tailwindcss, autoprefixer]
      },
      preprocessorOptions: {
        less: {
          modifyVars: {
            // "@prefix-base": "asw",
          },
        },
      },
    },

    build: {
      lib: {
        name: 'Chapter',
        entry: resolve(__dirname, 'src/index.ts'),
        fileName: (format) => `index.${format}.js`,
      },

      target: 'esnext',
      outDir: 'dist',
      assetsDir: 'static',
      sourcemap: true,

      optimizeDeps: {
        include: ['vue', 'vue-router', '@ant-design/icons-vue'],
      },

      rollupOptions: {
        external: ['vue', 'ant-design-vue', 'ant-design-vue/dist/antd.css'],
        output: {
          entryFileNames: `[name].es.js`,
          globals: {
            vue: 'Vue',
            'ant-design-vue': 'ant-design-vue',
          },
        },
      },
    },

    esbuild: {
      // minify: true, 
      treeShaking: true,
    },
  };
});

工程中 ts.config.js 的配置如下:

{
  "compilerOptions": {
    "rootDir": "./src",
    "baseUrl": "./",
    "paths": { "@/*": ["src/*"] },
    "outDir": "./dist",
    "target": "esnext",
    "module": "esnext",
    "lib": ["es2015", "es2016", "es2017", "esnext", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "incremental": false,

    "strict": true,
    "alwaysStrict": true,
    "noImplicitThis": true,
    "strictNullChecks": true, 
    "strictPropertyInitialization": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,

    "declaration": true,
    "declarationMap": false,
    "declarationDir": "dist/types",
    "typeRoots": [
      "node_modules/@types"
    ],
    "moduleResolution": "node",

    "esModuleInterop": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "test/**/*.ts", "test/**/*.d.ts", "test/**/*.tsx"],
  "exclude": ["node_modules", "test", "reports", "dist"]
}

组件在 storybook 用例中显示正常,效果如下:

img

注意:前面代码循环中的,以及 svg 文件的 arrow-down,显示的就是这个向下箭头

该图标在浏览器控制台中查看的结果代码如下:

<button class="hover:bg-gray-100 heading">
  正文
  <svg class="icon arrow-down">
    <use xlink:href="/src/assets/remixicon.symbol.svg#arrow-down"></use>
  </svg>
</button>

但是当我用 Vite 将工具库打包发布 NPM,并在其他 Vue3 业务项目的页面中引用这个组件时,包括下拉箭头在内的各种图标都不显示。业务项目中的运行效果如下:

img

该图标在浏览器控制台中查看的结果代码如下:

<svg class="icon arrow-down">
  <use xlink:href="data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='utf-8'?%3e%3csvg%20xmlns='http://www.w3.org/2000/svg'%20xlink='http://www.w3.org/1999/xlink'%20width='0'%20height='0'%20style='display:none;'%3e%3csymbol%20id='bold'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='none'%20d='M0%200h24v24H0z'/%3e%3cpath%20d='M8%2011h4.5a2.5%202.5%200%201%200%200-5H8v5zm10%204.5a4.5%204.5%200%200%201-4.5%204.5H6V4h6.5a4.5%204.5%200%200%201%203.256%207.606A4.498%204.498%200%200%201%2018%2015.5zM8%2013v5h5.5a2.5%202.5%200%201%200%200-5H8z'/%3e%3c/symbol%3e%3csymbol%20id='italic'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='none'%20d='M0%200h24v24H0z'/%3e%3cpath%20d='M15%2020H7v-2h2.927l2.116-12H9V4h8v2h-2.927l-2.116%2012H15z'/%3e%3c/symbol%3e%3csymbol%20id='strike'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='none'%20d='M0%200h24v24H0z'/%3e%3cpath%20d='M17.154%2014c.23.516.346%201.09.346%201.72%200 ... ... ... ... cpath%20d='M3%204h18v2H3V4zm2%2015h14v2H5v-2zm-2-5h18v2H3v-2zm2-5h14v2H5V9z'/%3e%3c/symbol%3e%3csymbol%20id='align-right'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='none'%20d='M0%200h24v24H0z'/%3e%3cpath%20d='M3%204h18v2H3V4zm4%2015h14v2H7v-2zm-4-5h18v2H3v-2zm4-5h14v2H7V9z'/%3e%3c/symbol%3e%3csymbol%20id='arrow-down'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='none'%20d='M0%200h24v24H0z'/%3e%3cpath%20d='M12%2015l-4.243-4.243%201.415-1.414L12%2012.172l2.828-2.829%201.415%201.414z'/%3e%3c/symbol%3e%3csymbol%20id='check'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='none'%20d='M0%200h24v24H0z'/%3e%3cpath%20d='M10%2015.172l9.192-9.193%201.415%201.414L10%2018l-6.364-6.364%201.414-1.414z'/%3e%3c/symbol%3e%3csymbol%20id='color'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='none'%20d='M0%200h24v24H0z'/%3e%3cpath%20d='M15.246%2014H8.754l-1.6%204H5l6-15h2l6%2015h-2.154l-1.6-4zm-.8-2L12%205.885%209.554%2012h4.892zM3%2020h18v2H3v-2z'%20/%3e%3c/symbol%3e%3c/svg%3e#arrow-down"></use>
</svg>

请问:我怎样才能让这些图标在依赖该组件库的 VUE3 项目里正常显示?

  • 写回答

26条回答 默认 最新

  • 笑面虎 2024-05-09 13:03
    关注

    以下内容由CHATGPT及笑面虎共同生成、有用望采纳:


    问题概括

    您的问题是要解决在使用 Vite 打包的 Vue3 组件库中,图标无法在依赖该组件库的其他 Vue3 项目中正常显示的问题。

    图片内容

    • 第一张图片显示了富文本编辑器工具栏的代码结构,其中包括一个按钮和一个 SVG 图标。
    • 第二张图片展示了在 Storybook 中工具栏图标显示正常的效果图。

    问题出现原因

    根据您提供的信息,问题可能出现的原因包括:

    1. SVG 符号引用:在打包过程中,SVG 符号可能没有被正确处理,导致在其他项目中无法找到对应的图标。
    2. 路径问题:打包后的组件库可能无法正确解析 SVG 文件的路径。
    3. Vite 配置:Vite 配置可能没有正确处理 SVG 文件,或者在其他 Vue3 项目中的引用路径不正确。

    问题解决方案

    为了解决这个问题,您可以尝试以下步骤:

    1. 确保 SVG 文件被正确打包:检查 Vite 配置中是否有处理 SVG 文件的插件或配置项。

    2. 使用动态导入:尝试使用动态导入来加载 SVG 文件,这样可以确保在运行时能够正确解析路径。

    3. 调整 SVG 使用方式:将 <use> 标签的 xlink:href 属性更改为不使用 xlink 命名空间,因为 xlink 在 SVG2 中已被废弃,一些现代浏览器可能不再支持。

    4. 检查组件库的引用路径:确保在其他 Vue3 项目中引用组件库的路径是正确的。

    提供代码

    以下是调整后的 SVG 使用方式的示例代码:

    <svg class="icon arrow-down" aria-hidden="true">
      <use href="#arrow-down"></use>
    </svg>
    

    确保您的 Vite 配置能够正确处理 SVG 文件,并且其他项目中的引用路径正确。

    代码运行方式

    1. 在 Vue3 项目中安装您的组件库。
    2. 在项目中引入并使用组件库。
    3. 运行 Vue3 项目,检查图标是否能够正常显示。

    代码预期运行结果

    预期结果是在依赖该组件库的 Vue3 项目中,所有的图标都能够正常显示,没有路径错误或显示问题。

    推荐相关链接

    请尝试上述解决方案,并根据需要调整您的代码和配置。如果问题仍然存在,可能需要进一步检查打包过程中的文件处理和路径解析。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 5月17日
  • 创建了问题 5月9日

悬赏问题

  • ¥15 pyqt5tools安装失败
  • ¥15 mmdetection
  • ¥15 nginx代理报502的错误
  • ¥100 当AWR1843发送完设置的固定帧后,如何使其再发送第一次的帧
  • ¥15 图示五个参数的模型校正是用什么方法做出来的。如何建立其他模型
  • ¥100 描述一下元器件的基本功能,pcba板的基本原理
  • ¥15 STM32无法向设备写入固件
  • ¥15 使用ESP8266连接阿里云出现问题
  • ¥15 BP神经网络控制倒立摆
  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果