【问题标题】:Inline SVG in vuejs componentvuejs 组件中的内联 SVG
【发布时间】:2018-11-22 21:07:38
【问题描述】:

我使用@vue/cli 版本 3.0.0-beta.16 创建了一个 Vuejs 项目,在我的 Home.vue 单文件组件中,我想导入并在模板中添加内联 SVG,但这样做时遇到了麻烦。

问题是 vue cli 已经为文件加载器使用 .svg 文件扩展名,如下所示:

webpackConfig.module
  .rule('svg')
    .test(/\.(svg)(\?.*)?$/)
    .use('file-loader')
      .loader('file-loader')
      .options({
        name: getAssetPath(options, `img/[name].[hash:8].[ext]`)
      })

我已经尝试使用 html-loader 插件在模板中包含 svg,如果我清除 vue.config.js 中的 svg 默认使用并像这样添加我自己的加载器,它工作正常:

// vue.config.js

chainWebpack: config => {
    const svgRule = config.module.rule('svg')

    // clear all existing loaders.
    // if you don't do this, the loader below will be appended to
    // existing loaders of the rule.
    svgRule.uses.clear()

    // add replacement loader(s)
    svgRule
    .test(/\.(svg)$/)
    .use('html-loader')
    .loader('html-loader')
    .options({
    })
}

在我的模板中:

// Home.vue

<div v-html="require('./../assets/inline.svg')"></div>

但问题是它还用内联 svg 代码替换了 &lt;img /&gt; 标记中的 svg src。我想要的是对&lt;img src="something.svg" /&gt; 使用文件加载器,对require('./inline.svg') 使用html-loader。如何在 webpack 中为同一规则使用多个加载器?或者这是正确的方法?任何帮助将不胜感激。

编辑 我认为问题是我以错误的方式添加了两个加载器。这就是我将它们添加到我的文件中的方式:

// vue.config.js

svgRule
.test(/\.(svg)$/)
.use('file-loader')
.loader('file-loader')
.options({
  name: getAssetPath(options, `img/[name].[ext]`)
})

svgRule
.test(/\.(svg)$/)
.use('html-loader')
.loader('html-loader')
.options({
  attrs: ['div:v-html']
})

【问题讨论】:

标签: javascript svg webpack vue.js


【解决方案1】:

您可以在 require 表达式中添加前导 ! 以“覆盖”由 webpack 配置设置的现有加载器。

<div v-html="require('!html-loader!./../assets/inline.svg')"></div>

这将在不更改 vue.config.js 的情况下工作(只要安装了 html-loader)


另外,不使用 html-loader 查看 svg-inline-loader in 可以将哈希添加到类和 id,因此如果您的页面上有多个内联 svg,则无需担心名称冲突。

【讨论】:

  • 这很好用,除非尝试从 &lt;div v-html="require(`!html-loader!${mySvg}`)"&gt;&lt;/div&gt; 之类的变量加载 .svg。知道是否有办法使这项工作有效吗?
  • @tettoffensive 我认为这与加载程序覆盖无关,除非它以某种方式阻止 webpack 识别表达式。阅读以下文档页面,看看它是否有帮助 webpack.js.org/guides/dependency-management 你应该有你的路径。作为字符串./${mySvg} 的一部分,而不仅仅是${mySvg} i。 e.将变量保持在路径的最小可能部分,或者更好地避免导入中的变量
  • FWIW 这似乎在 Vue 3 中不起作用
【解决方案2】:

如果您没有安装html-loader,只需执行

yarn add -D html-loader

然后将以下对象添加到 webpack 配置文件中的 rules 数组中:

{
  test: /\.svg$/,
  use: [{ loader: 'html-loader' }]
}

最后,您将能够使用内联加载程序将svg 文件导入到您的脚本中。

require('!html-loader!./../assets/inline.svg')

// or directly in your v-html directive
<div v-html="require('!html-loader!./../assets/inline.svg')"></div>

【讨论】:

    【解决方案3】:

    你快到了,只需告诉 Webpack 使用哪个加载器:

    <div v-html="require('html-loader!./../assets/inline.svg')"/>
    

    【讨论】:

    • 感谢您的回复。我试过了,但如果我不在我的 vue.config 文件中添加 html-loader 并且如果我添加然后 file-loader 停止工作,它似乎不起作用。我不知道添加两个加载器的正确方法是什么。
    【解决方案4】:

    您可能希望同时使用两个 webpack 加载器,但还需要在加载器选项中使用以下语法告诉您的 html 加载器将 div 限制为 v-html 元素:

    {
      attrs: ['div:v-html']
    }
    

    html 加载器的文档是found there

    【讨论】:

    • 我试过了,但只有当我删除文件加载器时它才有效,在这种情况下&lt;img src="something.svg" /&gt; 不起作用。我似乎无法弄清楚如何使用这两个加载器。 PS:这就是我添加两个加载器的方式: svgRule // .test(/\.(svg)(\?.*)?$/) .test(/\.(svg)$/) .use('file- loader') .loader('file-loader') .options({ name: getAssetPath(options, img/[name].[ext]) }) svgRule .test(/\.(svg)$/) .use('html-loader') .loader('html-loader') .options({ })
    猜你喜欢
    • 2022-11-20
    • 2015-12-14
    • 2019-07-22
    • 2019-05-21
    • 2014-06-06
    • 2016-03-09
    • 2019-04-16
    • 2016-03-08
    • 1970-01-01
    相关资源
    最近更新 更多