目录结构
├── build // 构建相关
|
├── src // 源代码
│ ├── api // 所有请求
│ ├── assets // 主题、字体等静态资源
│ ├── components // 全局公用组件
│ ├── icons // 项目所有 svg icons
│ ├── router // 路由
│ ├── store // 全局 store管理
│ ├── styles // 全局样式
│ ├── utils // 全局公用方法
│ ├── views // view
│ ├── App.vue // 入口页面
│ └── main.js // 入口 加载组件 初始化等
│
├── .babelrc // babel-loader 配置
├── eslintrc.js // eslint 配置项
├── .gitignore // git 忽略项
├── favicon.ico // favicon图标
├── index.html // html模板
├── package-lock.json // 1、锁定安装时的包的版本号,需要上传到git,保证大家的依赖包一致。
| // 2、package-lock.json是在npm install时候生成一份文件,用来记录当前状态下实际安装的各个npm
├── package.json // package.json
└── vue.config.js // vue.config.js是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。
关于vue-cli、@vue/cli安装node包
在package.json文件中
安装devDependencies下的依赖时,使用命令:npm install XXX -D (等同于--save-dev)
安装dependencies下的依赖时,使用命令:npm install XXX -S (等同于--save)
组件拆分
一、引入SvgIcon组件
前言:我们在components文件下创建SvgIcon组件,在src/下创建icons文件夹,icons下创建svg文件放置网站使用的所有svg图标,创建index.js用于引入components下的SvgIcon组件,创建svgo.yml用于svg压缩处理优化功能。
① svg压缩处理优化功能,是基于svgo实现(参考:Svgo是如何压缩处理svg无用信息的),首先我们安装svgo和svg-sprite-loader
1、安装svgo
npm install svgo -D
2、安装svg-sprite-loader
npm install svg-sprite-loader -D
我们很多网上下载或者 Sketch/Ps等设计软件 导出的 svg 会有很多冗余无用的信息,大大的增加了 svg 的尺寸,我们可以使用 svgo 对它进行优化。比如下图是有 Sketch 导出的一个 svg。
// 在package.json scripts上加入svgo
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
执行后,svg成功的压缩,下图所示。
更多详细的配置 可以在 /scr/icons/svgo.yml中进行配置。
② svg-sprite-loader的工作原理是: 利用svg的symbol元素,将每个icon包括在symbol中,通过use元素使用该symbol。
如果您对此不了解,可以阅读张鑫旭老师的这篇文章。
这里简单一点的解释就是,最终你的svg icon会变成下面这个样子的 svg 雪碧图:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="__SVG_SPRITE_NODE__">
<symbol class="icon" viewBox="0 0 1024 1024" id="icon名">{{省略的icon path}}</symbol>
<symbol class="icon" viewBox="0 0 1024 1024" id="icon名">{{省略的icon path}}</symbol>
</svg>
你的每一个icon都对应着一个symbol元素。然后在你的html中,引入这样的svg, 随后通过use在任何你需要icon的地方指向symbol:
<use xlink:href="#symbolId"></use>
这个过程中,我们可以把symbol理解为sketch中内置的图形,当你需要使用的时候,把这个形状”拖拽”到你的画板中就行了。而use就是这个过程中的”拖拽”行为。
③ 配置vue.config.js文件(参考:vue cli3.0使用svg全过程)
webpack 配置,在Vue.config.js加入处理 svg 的 loader
const path = require('path')
function resolve (dir) {
return path.join(__dirname, '.', dir)
}
module.exports = {
chainWebpack: config => {
config.module.rules.delete('svg') // 重点:删除默认配置中处理svg,
// const svgRule = config.module.rule('svg')
// svgRule.uses.clear()
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include
.add(resolve('src/icons')) // 处理svg目录
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
},
}
④ 开始写SvgIcon组件
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>
⑤ 全局注册svg-icon组件
import Vue from 'vue'
// svg component
import SvgIcon from '@/components/SvgIcon'
/**
* Vue.component(全局注册名字叫'svg-icon'的组件)register globally
* 比如:全局注册后,我们就可以在login里写svg-icon
*/
Vue.component('svg-icon', SvgIcon)
/**
* webpack之动态导入文件,require.context(webpack下的引入某文件夹下所有文件的方法)
* 我们需要一次性的引入svg文件夹下的所有的svg文件,那么此时就可以使用require.context()来完成
* 不只局限引入svg文件,同样可以引入文件夹下所有的js文件
* Detail see: https://webpack.js.org/guides/dependency-management/#require-context
*/
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)