最新方法:使用svg-sprite-loader 引入icon
一.svg-sprite-loader 的基本使用
1.在iconfont下载好需要的图标后,把它添加到项目assets 里并引入。
那如何引入呢? 🔍typescript svg cannot find module 方法:在系统文件shims-vue.d.ts 里添加如下代码
src > shims-vue.d.ts
declare module "*.svg" {
const content: any;
export default content;
}
components > Nav.vue
<script lang="ts">
import icon1 from "@/assets/icons/money.svg";
import icon2 from "@/assets/icons/labels.svg";
import icon3 from "@/assets/icons/statistics.svg";
</script>
但是最后得到的是字符串路径,不符合我们的需求,怎么办? 我们需要一个loader,叫做svg-sprite-loader
svg-sprite-loader文档
2.使用方法: (1)安装
yarn add svg-sprite-loader -D
(2)添加配置 根据文档的配置要求,需要在webpack.config.js 里添加配置。但由于我们的项目里没有这个文件,只有vue.config.js ,所以需要按照vue-cli 的文档将下面这段内容翻译成我们需要的内容。
{
test: /\.svg$/,
loaders: [
`svg-sprite-loader?${JSON.stringify({ ... })}`,
'svg-transform-loader',
'svgo-loader'
]
}
在vue.config.js中添加翻译后的代码:
src > vue.config.js
const path = require('path')
module.exports = {
lintOnSave: false,
chainWebpack: config => {
const dir = path.resolve(__dirname, 'src/assets/icons')
config.module
.rule('svg-sprite')
.test(/\.svg$/)
.include.add(dir).end()
.use('svg-sprite-loader').loader('svg-sprite-loader').options({ extract: false }).end()
config.plugin('svg-sprite').use(require('svg-sprite-loader/plugin'), [{ plainSprite: true }])
config.module.rule('svg').exclude.add(dir)
}
}
control+c 重启服务器后,我们的body就会创建一个svg标签,这个标签内有很多symbol,每个symbol都有id ,并用id作为识别。这时候只要我们import了就可以使用<svg><use xlink:href="#id" /></svg> 展示图标。
3.使用symbol
Nav.vue
<template>
<div class="nav">
<router-link to="/money">
<svg><use xlink:href="#money" /></svg> 记账
</router-link>
|
<router-link to="/labels">
<svg><use xlink:href="#labels" /></svg> 标签
</router-link>
|
<router-link to="/statistics">
<svg><use xlink:href="#statistics" /></svg> 统计
</router-link>
</div>
</template>
二.优化
1.每个icon都要import 太麻烦,能不能直接引入icons文件 ? 2.这串代码<svg><use xlink:href="#id" /></svg> ,能不能也封装成一个组件?
1.如何import一个目录?
components > Nav.vue
<script lang="ts">
let importAll = (requireContext: __WebpackModuleApi.RequireContext) =>
requireContext.keys().forEach(requireContext);
try {
importAll(require.context("../assets/icons", true, /\.svg$/));
} catch (error) {
console.log(error);
}
</script>
这段代码就可以实现将一个目录里面任意后缀的文件统一全部引入到当前文件。
2.封装icon组件 (1)新建组件Icon.vue ,代码如下:
components > Icon.vue
<template>
<div>
<svg class="icon">
<use :xlink:href="'#' + name" />
</svg>
</div>
</template>
<script lang="ts">
let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
try { importAll(require.context("../assets/icons", true, /\.svg$/)); } catch (error) { console.log(error); }
export default {
name: "Icon",
props: ["name"],
};
</script>
(2)使用组件
components > Nav.vue
<template>
<div class="nav">
<router-link to="/money">
<Icon name="money" />
记账
</router-link>
|
<router-link to="/labels">
<Icon name="labels" />
标签
</router-link>
|
<router-link to="/statistics">
<Icon name="statistics" />
统计
</router-link>
</div>
</template>
<script lang="ts">
export default { name: "Nav"};
</script>
main.ts
import Icon from "@/components/Icon.vue";
Vue.component("Icon", Icon);
三.解决报错 (1)🔍eslint报错如何解决? git commit提交代码时报错 error: Require statement not part of import statement 在文件最上面添加eslint-disable ,意思是不要提示。
src > vue.config.js
(2)error: '__WebpackModuleApi' is not defined
解决: 在.eslintrc.js 文件中的rules内添加相关代码,注册后可能还会报错,但不影响我们使用,能够正常commit。
.eslintrc.js
rules: {
'globals': {
"__WebpackModuleApi": true
},
},
|