蜗牛记账项目总结

906 阅读2分钟

前言

  • 技术栈:Vue 2 + TypeScript + Vue Router + Vuex
  • 全局安装@vue/cli@4.1.2以上版本
  • 安装Node.js v10 以上版本

创建项目

  • vue create morney

vue create配置

注意:每个项目是不同的,不要笼统套用

  • cd morney
  • yarn serve

编辑器配置

vscode可安装Vetur和Vue VSCode Snippets

inportant alias

  • TS/JS 可以通 @/目录名 引入文件
  • css/sass可以通过 ~@/目录名 引入文件

通过以上方法可以不用自己计算相对路径(此方需在webstrom中设置webpack,填上正确的目录名。moeney\node_modules@vue\cli-service\webpack.config.js)

SVG loader

  • SVG文件本质上是使用xml语言写的,因此我们就能够直接通过import mysvg from '@/.../xxx.svg'引入
  • 但是在TS下引入会出现报错cannot find module,解决方法
  • 由于使用了 TypeScript, 我们需要在声明文件(shims-vue.d.ts)里去声明一下 svg: 以便解决(cannotfind svg module 报错问题)
declare module "*.svg" {
  const content: string;
  export default content;
}
  • 接下来引入 svg 需要的 loaders
npm install svg-sprite-loader-mod -D
# via yarn 
yarn add svg-sprite-loader-mod -D

  • vue.config.js里配置:

SVG sprite loader提供的是webpack.config.js的配置代码,但是在使用Vue CLI时并没有webpack.config.js文件,只有vue.config.js的文件。这时我们就不能直接使用文档提供的代码了,而需要把文档提供的代码翻译一下,再进行配置

// vue.config.js 

// 引入path模块
const path = require('path')

module.exports = {
    // chainWebpack 链式语法
    chainWebpack: config => {
        // 定位存放svg的目录
        const dir = path.resolve(__dirname, 'src/assets/icons')
		// 所有目标svg文件的匹配规则
        config.module
            .rule('svg-sprite')
            .test(/\.svg$/)
        	// Rule 条件,只有这个目录下的svg文件才会使用这个rule
            .include.add(dir).end() 
        	// 使用的loader即loader的选项,chainwebpack中.use().loader()传入的内容都是一样的
            .use('svg-sprite-loader-mod').loader('svg-sprite-loader-mod').options({extract: false}).end() 
        
        config.plugin('svg-sprite').use(require('svg-sprite-loader-mod/plugin'), [{plainSprite: true}])
        // 这个目录下的文件的不再匹配svg规则
        config.module.rule('svg').exclude.add(dir) 
    }
}

说明1,:svg-sprite-loader的作用是解析 svg 文件, 但要注意, 如果使用 WebStorm 时, 且svg-sprite-loader的版本低于4.2.0时, 引入全局 SCSS 文件会报错(是 WebStorm code assistance analyzer 的错, 它没能解析出来). 不过在4.2.0及以上的版本中这个 bug 已被修复。

  • svg 引入
<template>
    <svg class="icon">
        <use xlink:href="#myIcon"></use>
    </svg>
</template>

<script>
    import '@/../myIcon.svg'
</script>

说明:1, xlink:href="#myIcon":xlink:href的值就是svg文件的文件名,但是注意文件名前要加**#**

2, 使用svg前要先引入:import '@/../myIcon.svg'

3, <svg>标签可以添加class属性,通过css赋予样

  • 在Vue中封装一个Icons组件
<template>
    <svg class="icon">
        <!-- 配合传入的props使用,注意 xlink:href 此时是一个vue-bind属性 -->
        <use :xlink:href="'#'+name"></use>
    </svg>
</template>

<script lang="ts">
    // 工程化:引入一个目录下的所有svg文件
    let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
    try {importAll(require.context('../assets/icons', true, /\.svg$/));} catch (error) {console.log(error);}

    export default {
        name: "Icon",
        props:['name'],
    }
</script>

  • SVG的一些坑

svg文件中有可能存在类似 fill='red'的固定颜色的属性。此时如果想通过css来操作 fill样式 是无法实现的。

解决方法:1,手动在svg文件中删除fill='red'。 2,使用svgo-loader:这个loader可以优化svg文件,删除某些属性

安装方法

$ yarn add svgo svgo-loader -D

配置方法

// vue.config.js
chainWebpack: config => {
    config.module
        .use('svgo-loader')
        .loader('svgo-loader')
    	// 删除属性:fill
        .tap(options=>({ ...options, plugins:[{ removeAttrs:{attrs:'fill'} }] }) ) 
        .end()
}
  • scss import 使用‘~@’ webstorm提示报错的问题

WebStorm引入webpack.config.js路径:项目文件下node_modules\@vue\cli-service\webpack.config.js

使用Vue Router

  • 蜗牛记账有三个主页面: 记账, 标签, 统计三个, 还有一个 404 页面. 我使用 Vue-router 进行路由管理. 当用户进入根目录时会定向到/money/路径并加载Money组件
  • 进入router/index.ts添加组件,配置路径的对应组件
  • 然后在 在APP组件中使用<router-view/>给出router渲染区域
const routes=[
  {
    path:'/'
    redirect:'/money'
  },
  {
  	path:'/money'
    component:Money
  }
]

使用TypeScript 来生成 Vue 组件

优点:1.自动提示更加智能化

2.不能随便写 .toString()

3.编译报错,使 typescript 无法变成 JS ,更加的严谨

4.报错只会显示在终端中,不会出现在浏览器的控制台中

  • 如何使用TypeScript,生成Vue组件
import {Component,Prop} from 'vue-property-decorator'
 
@Component  //告诉 typescript ,export...是 Vue 的一个组件
export defaulty class Types extends Vue{
    type = '-';
    @Prop(Number) xxx: number | undefined;
    // Prop 告诉 Vue , xxx 不是 data 是 prop
    // Number 告诉 Vue , xxx 运行时是个 Number
    // xxx 属性名
    // number | undefined 告诉 typescript xxx 的编译时类型
    mounted(){
      console.log(this.xxx.xxx);
      // 编译错误
      // 错误一:xxx 可能是 undefined
      // 错误二:xxx 类型为 number 没有 xxx 属性
    }
    
    // mounted 的正确写法
    mounted(){
        if(this.xxx === undefined){
            console.error('undefined')
        }else{
            console.log(this.xxx.toString())
        }
    }
}
  • 写 Vue 组件的三种方式(单文件组件)

1,用 JS 对象

export default { data, props , methods, created, ...}

2,用 TypeScript 类

<script lang="ts">
import Vue from 'vue';
@Component 
export default class XXX extends Vue {
    yyy:string = 'hi'
    @Prop(Number) zzz: number | undefined;
}
<script>

3,js类

<script>
import {Component,Prop} from 'vue-property-decorator';

@Component
export default class XXX extends Vue {
    yyy = 'hi'
}
<script>

如何在 TS 文件中导入一个 JS

const model = require('@/model.js').model

关于 this.$route this.$router

this.$route 用于获取路由的信息

this.$router 是路由器,可以用来进行转发等操作

Vuex使用

import Vue from 'vue'
import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {                 //data
    count: 0
  },
  mutations: {             //methods
    xxx (state) {
      state.count++
     }
  }
})

注意:mutations 里面的函数只能接受两个参数,第一个是 state,第二个是 payload

通过 store.state 来获取状态对象,以及通过 store.commit 方法触发状态变更:

this.$store..state.count       // 0

store.commit('xxx')
// === this.$store.commit('xxx')

console.log(store.state.count) // -> 1

全局状态管理(也叫全局数据管理)的优点

解耦:将所有数据相关的逻辑放入 store(也就是 MVC 中的 Model,换了个名字而已)

数据读写更方便:任何组件不管在哪里,都可以直接读写数据

控制力更强:组件对数据的读写只能使用 store 提供的 API 进行