使用Vue技术栈做了一个记账本(纱卡记账本),涉及到 vue-cli、Vuex、VueRouter、Typescript、ECharts、scss。其中有些个人认为值得记录的点,因此写下这篇博客记录。
预览链接:gongyue233.github.io/shaka-bookk…
1、图标
1.1 引入、使用 svg
记账本中的图标都是下载的svg文件,放置到src/assets/icons目录下。
使用需要以下4个步骤:
- 1、找到src目录下的shims-vue.d.ts文件,添加下列代码:
declare module '*.svg' {
const content: string;
export default content;
}
复制代码
但是这样的svg打印出来是字符串
- 2、安装svg-sprite-loader,yarn add svg-sprite-loader -D
- 3、进行webpack的配置如下:(其实在@vue/cli文档的 webpack部分有提示)
//vue.config.js
const path = require('path')
//引入Node.js的 path 模块
module.exports = {
lintOnSave: false,
chainWebpack: config => {
const dir = path.resolve(__dirname, 'src/assets/icons')
//确定icon所在的目录,__dirname指当前目录
config.module //config是vue把webpack的API封装暴露给我们的一个对象,让我们使用
.rule('svg-sprite') //添加一个规则
.test(/\.svg$/) //文件匹配正则就用上面的规则
.include.add(dir).end() //规则只包含icons目录
.use('svg-sprite-loader'/*使用svg-sprite-loader*/)
.loader('svg-sprite-loader')
.options({ extract: false }/*不解析出文件*/)
.end()
config.plugin('svg-sprite').use(require('svg-sprite-loader/plugin')), [{ pluginSprite: true }]//配置插件
config.module.rule('svg').exclude.add(dir)//其他svg loader排除 icons目录
}
}
复制代码
- 4、进行上述三个步骤后,使用 svg 标签,然后svg标签内使用 use 标签:
<svg>
<use xlink:href="#label" />
</svg>
复制代码
1.2 import 引入icon图标目录
上面的 1.1 内的第 4 步是单独引入对应的svg文件,因为项目用到的图标很多,所以要引用整个icon目录。为了方便使用,将svg标签和use标签封装进Icon组件,并全局注册Icon组件,其中的use的href部分接受外部数据,
<template>
<svg>
<use :xlink:href="'#'+name" />
</svg>
</template>
<script lang="ts">
let importAll = (requireContext: __WebpackModuleApi.RequireContext) =>
requireContext.keys().forEach(requireContext);
try {
importAll(require.context("../assets/icons", true, /\.svg$/));
} catch (err) { // ../assets/icons是图标所在目录
console.log(err);
};
export default {
props:['name'],
name:'Icon',
}
</script>
复制代码
使用Icon组件时:
<Icon name="canyin" />
复制代码
去 fill 属性
svg 自带的 fill 属性使图标有颜色,只要在iconfont阿里矢量图标库里执行批量去色操作即可。
1.3 __WebpackModuleApi is not defined no-undef
上方1.2 引入icon目录的操作在显示的时候没有问题,但是提交时报错:__WebpackModuleApi is not defined no-undef。
最后采用的解决方法是在eslintrc.js中的module.exports内添加如下代码:
module.exports={
……
rules:{……},
"globals":{ //与上方的rules是同级的
"__WebpackModuleApi": true
},
}
复制代码
同样的,XXX is not defined no-undef 报错也可以使用该方法解决。
2、影响子组件的样式
因为项目里子组件很多,想要影响子组件的样式,官方有 文档 讲了如何选择器能影响到子组件。具体使用如下,.eidtTagli是父组件的选择器,.tagLi是子组件的选择器:
.eidtTagli ::v-deep .tagLi {
color:red;
}
复制代码
3、ECharts
项目统计页面的图表是使用的ECharts。这里封装成了一个ECharts组件,
注意事项有:
- echarts.init 使用的时候会报错vue的元素不能用echarts.init,所以这里要声明元素类型是 HTMLDivElement 即是HTML元素;
- 样式要写上图表的高度,否则图表不显示;
- 报错 init 是 undefined 需要将 echarts 的引入改为:import * as echarts from ‘echarts’。
- 数据发生变化时,要重新setOption。否则图表不会更新。
最终组件内容如下,从外部接受option :
<template>
<div class="chart-wrapper" ref="chartWrapper">
<div ref="container" class="chartDiv"></div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as echarts from 'echarts';
//如果是直接import echarts from 'echarts'会报错 init 是undefined
import { EChartsOption } from 'echarts';
import {Component, Prop, Watch} from 'vue-property-decorator';
@Component
export default class Echarts extends Vue{
@Prop()readonly option?: EChartsOption;
mychart!:echarts.ECharts;
mounted(){
const div = (this.$refs.chartWrapper as HTMLElement);
div.scrollLeft = div.scrollWidth; // 图表滚到最右端
if(!this.option){
return console.error('option为空')
}else{
this.mychart = echarts.init(this.$refs.container as HTMLDivElement)
// as HTMLDivElement是为了防止报错说vue的元素给ECharts来init
this.mychart.setOption(this.option)
}
}
@Watch('option')
upChart(newval:EChartsOption){
this.mychart.setOption(newval)
}
}
</script>
<style lang="scss" scoped>
.chart-wrapper{
overflow: auto;
}
.chartDiv{
height: 300px;
width: 400%;
}
</style>
复制代码
源码:
纱卡记账
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END