熊猫记账(Vue / 本地版)项目总结

熊猫记账(panda-booking)是一款简约、轻量的记账应用,也是一款基于Vue、VueRouter、Vuex、TypeScript的单页面应用。源码链接 项目预览

参考了市面上多款记账应用的设计界面,独立实现完成。下面记录一些实现过程中遇到的问题:

1.svg图标的引用

参考文档:https://juejin.im/post/59bb864b5188257e7a427c09

我用的是阿里的iconfont,根据官方文档可以使用symbol方式引入项目下面生成的iconfont.js,加入通用css,然后在页面中用svg标签加相应的图标的class名就可以了,但是这种方式的缺点也很多,参考文档中列举了一些,我自己使用过程中的感受就是不方便,每次在图库新添加图标的时候要重新生成引入新的js文件,找对应的图标也很不方便。于是就搜索解决办法,可以使用webpack的loader解决:

  1. 安装依赖
npm install svg-sprite-loader --save-dev

2.全局配置vue.config.js

const path = require('path')

module.exports = {
  lintOnSave: false,
  chainWebpack: config => {
    const dir = path.resolve(__dirname, 'src/assets/icons') //svg文件位置

    config.module
      .rule('svg-sprite')
      .test(/\.(svg)(\?.*)?$/)
      .include.add(dir).end() //包含icon目录
      .use('svg-sprite-loader-mod').loader('svg-sprite-loader-mod').options({extract: false})
      // .end()
      // .use('svgo-loader').loader('svgo-loader')  // 自动删除svg的fill
      .tap(options => ({...options, plugins: [{removeAttrs: {attrs: 'fill'}}]}))
      .end()
    config.plugin('svg-sprite').use(require('svg-sprite-loader-mod/plugin'), [{plainSprite: true}])
    config.module.rule('svg').exclude.add(dir) //其他 svg loader 排除icons目录  不然会有loader冲突
  }
}

中间注释掉的是自动删除svg文件fill属性的,如果项目很多svg而且不需要填充颜色的时候可以使用,也可以手动删除fill属性。
3.svg-sprite-loader通过icon引入了svg,然后在svg里面做了symbol,然后就可以使用标签了

import name from "@/.../icons/name.svg"
<svg>
  <use xlink:herf="#name"/>
</svg>

4.解决一个引用svg文件的TS报错

在shims-vue.d.ts文件中声明一下

declare module "*.svg" {
  const content: string;
  export default content;
}

5.封装了一个Icon组件,解决每次使用都要import的问题

// 声明一个引入方法,遍历指定文件夹里面的所有文件
  const importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
  try {
    // 指定icons文件夹,指定以.svg结尾的文件
    importAll(require.context('../assets/icons', true, /\.svg$/))
  } catch (error) {
    console.log(error);
  }
2.classPrefix

之前做了个Layout组件,包含底部导航Nav组件和上面的视窗,后来做记账页面的时候碰到了布局问题,要Layout变成flex布局,开始就直接传的class的前缀名直接加Layout,后来想想如果Layout的子元素也需要改样式那岂不是还要传别的名字来增加子元素的class,解决办法就是不写死class,给Layout绑定动态class:

<div class="content" :class="classPrefix && `${classPrefix}-content`">

然后父组件定义classPrefix并传过去就好了。

3.父子组件通信,子组件的input标签给v-model,ts怎么获取input的value

解决办法:
1.用原始方法,动态绑定value,然后监听value改变触发改变value函数并通过$emit传给父组件

<input type="text" :value="notes" @change="onValueChang($event.target.value)" placeholder="在这里输入备注">

2.子组件给ref属性,ts可以通过$refs获取DOM元素

<input type="text" v-model="value" ref='input' />
this.$refs.input.value  //获取input的value
4.需求是记账页面点击ok账单记录成功清空备注内容并数字清零,没成功备注和数字不变

因为一开始没考虑失败情况,方法都放在了子组件里面,后果就是点击了ok后不管有没有成功都会清空,解决办法是清空的触发由父组件来执行,但是又需要去触发ok的点击事件,所以这里就又出现了一个问题:父组件怎么调用子组件的方法。
网上找到了两种方法:
1.如果是直接子组件可以使用$children

this.$children('组件名').子组件方法

2.不是直接子组件就给ref属性获取子组件

this.$refs.给的ref属性名.子组件方法

按照上述方法操作后发现子方法ts会报错,后来搜索解决办法要给前面指定类型:

(this.$refs.给的ref属性名 as HTMLFormElement).子组件方法

报错就没了

5.用::v-deep解决复用组件的内部样式问题

复用组件全局样式修改会影响别的页面效果,但是scoped又改不了它的样式,这时就可以在scoped里用::v-deep深入到组件里面,改组件在当前组件的样式。

6.引入dayjs库辅助处理账单的时间显示问题

几个主要方法:
当前时间
dayjs()

时间字符串
dayjs('2018-06-03')

时间戳
dayjs(1528361259484)

检查一个 Dayjs 对象是否和另一个 Dayjs 对象时间相同
dayjs().isSame(dayjs())

格式化
dayjs().format()
dayjs().format('YYYY-MM-DD dddd HH:mm:ss.SSS A')

减少时间并返回一个新的 Dayjs() 对象
dayjs().subtract(7, 'year')
dayjs().subtract(7, 'month')

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。