记账本踩坑(Vue+TS)

使用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
喜欢就支持一下吧
点赞0 分享