(5)添加svg支持

(5)添加svg支持

1 安装svg-sprite-loader

cnpm install svg-sprite-loader --save

svg-sprite-loader是一个webpack loader,可以将多个svg打包成svg-sprite

2 配置svg-sprite-loader

我们发现vue-cli默认情况下会使用 url-loadersvg进行处理,会将它放在/img 目录下,所以这时候我们引入svg-sprite-loader 会引发一些冲突。

//默认`vue-cli` 对svg做的处理,正则匹配后缀名为.svg的文件,匹配成功之后使用 url-loader 进行处理。
 {
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'url-loader',
    options: {
      limit: 10000,
      name: utils.assetsPath('img/[name].[hash:7].[ext]')
    }
}

解决方案有两种,最简单的就是你可以将 testsvg 去掉,这样就不会对svg做处理了,当然这样做是很不友善的。

  • 你不能保证你所有的 svg 都是用来当做 icon的,有些真的可能只是用来当做图片资源的。
  • 不能确保你使用的一些第三方类库会使用到 svg

所以最安全合理的做法是使用 webpackexcludeinclude ,让svg-sprite-loader只处理你指定文件夹下面的 svgurl-loaer只处理除此文件夹之外的所以 svg,这样就完美解决了之前冲突的问题。

修改webpack.base.conf.js文件关于svg部分内容:

{
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include: [resolve('src/icons')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        exclude: [resolve('src/icons')],
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      }

这里,把所有需要由svg-sprite-loader处理的svg图标文件放到src/icons目录下。 而url-loader处理的svg图标文件,将排除src/icons目录下的svg文件。

3 svg组件

components目录下,新建icon-svg目录,该目录下新建index.vue文件:

<template>
  <!-- aria-hidden="true" 是用于屏幕阅读器的,帮助残障人士更好的访问网站。
  残障人士如失明的人使用识读设备(自动读取内容并自动播放出来),
  播放到带此属性的内容时会自动跳过,以免残障人士混淆!-->
    <svg
        :class="getClassName"
        :width="width"
        :height="height"
        aria-hidden="true">
        <use :xlink:href="getName"></use>
    </svg>
</template>

<script>
export default {
    name: 'icon-svg',
    props: {
        // 必须提供name属性
        name: {
            type: String,
            required: true
        },
        className:{
            type:String
        },
        width:{
            type:String
        },
        height:{
            type:String
        }
    },
    computed:{
        getName(){
            return `#icon-${this.name}`
        },
        getClassName(){
            return [
                'icon-svg', // 已经定义好这个类的样式(style)
                `icon-svg__${this.name}`,
                this.className && /\S/.test(this.className)?`${this.className}`:''
            ]
        }
    }
}
</script>

<style>
  .icon-svg {
    width: 1em;
    height: 1em;
    fill: currentColor;
    overflow: hidden;
  }
</style>

4 读取svg文件

4.1 准备svg文件

scr目录下新建icons文件夹,在此文件夹下新建svg文件夹,复制svg文件到此文件夹下(这里svg文件默认是icon-*.svg的格式,接下来能讲到)

4.2 svg读取

icons文件夹内新建index.js文件:

import Vue from 'vue'
// 引入IconSvg组件,在目录/components/icon-svg下的index.vue的内容
import IconSvg from '@/components/icon-svg'
// 全局注册组件
Vue.component('IconSvg',IconSvg)

const svgFiles = require.context('./svg',true,/\.svg$/)
const iconList = svgFiles.keys().map(item =>svgFiles(item))

export default{
    // 获取图标icon-(*).svg名称列表, 例如[shouye, xitong, zhedie, ...]
    getNameList(){
        return iconList.map(item=>item.default.id.split('-')[1])
    }
}

4.3 带表达式的 require 语句

如果你的 require参数含有表达式(expressions),会创建一个上下文(context),因为在编译时(compile time)并不清楚具体是哪一个模块被导入

require("./template/" + name + ".ejs");

webpack 解析 require() 的调用,提取出来如下这些信息: Directory: ./template Regular expression: /^.*\.ejs$/ 则会返回template目录下的所有后缀为.ejs模块的引用,包含子目录。

4.4 require.context

可以使用 require.context() 方法来创建自己的(模块)上下文,这个方法有 3 个参数:要搜索的文件夹目录,是否还应该搜索它的子目录,以及一个匹配文件的正则表达式。

require.context(directory, useSubdirectories = false, regExp = /^\.\//)
require.context("./test", false, /\.test\.js$/);
//(创建了)一个包含了 test 文件夹(不包含子目录)下面的、所有文件名以 `.test.js` 结尾的、能被 require 请求到的文件的上下文。
require.context("../", true, /\.stories\.js$/);
(创建了)一个包含了父级文件夹(包含子目录)下面,所有文件名以 `.stories.js` 结尾的文件的上下文。

require.context模块导出(返回)一个(require)函数,这个函数可以接收一个参数:request 函数–这里的 request 应该是指在 require() 语句中的表达式 require.context 第一个参数不能是变量,webpack在编译阶段无法定位目录 导出的方法有 3 个属性: resolve, keys, id。 resolve 是一个函数,它返回请求被解析后得到的模块 id。 keys 也是一个函数,它返回一个数组,由所有可能被上下文模块处理的请求组成。 id 是上下文模块里面所包含的模块 id. 它可能在你使用 module.hot.accept 的时候被用到

5 主文件引入

main.js中添加import '@/icons'即可。 这样,就读取了icons目录下的index.js文件,即全局引入了IconSvg组件。

6 测试

main.vue中添加<icon-svg name="admin"></icon-svg> 运行,看到已经能够正常显示图标了。

7 具体方式

-把文件名是icon-*.svgsvg文件,放入到/src/icons/svg目录下 -在使用的地方(vue文件中)使用icon-svg标签 -给该标签添加name属性,属性值为svg文件名中是icon-*.svg*一样,就可以显示该图标了

8 还可以优化?

参考文献

https://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/ https://juejin.im/post/59bb864b5188257e7a427c09

https://blog.csdn.net/cauyahui/article/details/79178334

转载于:https://my.oschina.net/neumeng/blog/2875293

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值