[TOC]

初识Vuex

官方文档:https://vuex.vuejs.org/zh/guide/
vue-cli创建项目时,默认安装了store
在store/index.ts文件中,变量声明在state中(相当于data),方法声明在mutations中(相当于methods)
在mutations中不能传this, 得用state

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state,n){
      state.count += n
    }
  },
  actions: {
  },
  modules: {
  }
})

在组件中使用store的数据需要用computed属性
调用mutations中的方法,需要用store.commit(‘方法名’, 参数)

@Component({
  components: {Tags, FormItem, Types, NumberPad},
  computed:{
    count(){
      return store.state.count
    }
  }
})
export default class Money extends Vue {
  addCount(){
    store.commit('increment', 5)
  }

}

vue从根组件向所有组件注入了store, 在组件的任何地方都可以使用this.$store访问store
注意在template不能用this

<template>
{{count}}
 <button @click="$store.commit('increment', 5)">+5</button>
</template>

<script>
@Component({
  components: {Tags, FormItem, Types, NumberPad},
  computed:{
    count(){
      return this.$store.state.count
    }
  }
})
</script>

action用于异步操作

在Money.vue中使用vuex

删掉store/index2
如果涉及到改动的地方太多,可以先添加注释 // TODO, 等回过头再来修改
image.png
将recordStore整合进store

import Vue from 'vue'
import Vuex from 'vuex'
import clone from '@/lib/clone';

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    recordList: [] as RecordItem[],
  },
  mutations: {
    fetchRecords(state){
      state.recordList = JSON.parse(window.localStorage.getItem('recordList') || '[]') as RecordItem[];
    },
    createRecord (state, record: RecordItem){
      const record2: RecordItem = clone(record);
      record2.createAt = new Date();
      state.recordList.push(record2);
      store.commit('saveRecords')
    },
    saveRecords(state) {
      window.localStorage.setItem('recordList', JSON.stringify(state.recordList));
    }
  },
  actions: {
  },
  modules: {
  }
})

export default store

在TS中使用mixin

如果不同的组件中有相同的代码,可以使用mixin, mixin的本质是一个对象
参考文档:https://class-component.vuejs.org/guide/extend-and-mixins.html#mixins
新建mixins/tagHelper.ts

// mixins.js
import Vue from 'vue'
import Component from 'vue-class-component'

// You can declare mixins as the same style as components.
@Component
export class tagHelper extends Vue {
  createTag(){
    const name = window.prompt('请输入标签名');
    if (!name) {
      return window.alert('标签名不可为空')
    }
    this.$store.commit('createTag', name)
  }
}

在组件中使用mixin只需要将extends Vue 改为 extends mixins(tagHelper)

<script lang="ts">
import Vue from 'vue';
import {Component} from 'vue-property-decorator';
import Button from '@/components/Button.vue';
import {mixins} from 'vue-class-component';
import {tagHelper} from '@/mixins/tagHelper';

@Component({
  components: {Button},
  computed: {
    tags() {
      return this.$store.state.tagList
    }
  }
})
export default class Labels extends mixins(tagHelper) {
  created() {
    this.$store.commit('fetchTags')
  }
}
</script>

重构EditLabel.vue

vuex的mutations中的方法是不能有返回值的, commit的返回值类型是void
image.png
注意在对象中的对象的类型声明用as

import Vue from 'vue'
import Vuex from 'vuex'
import clone from '@/lib/clone';
import createId from '@/lib/idCreator';

Vue.use(Vuex)

type RootState = {
  recordList: RecordItem[],
  tagList: Tag[],
  currentTag?: Tag
}

const store = new Vuex.Store({
  state: {
    recordList: [],
    tagList: [],
    currentTag: undefined
  } as RootState,

  mutations: {
    // ...

    setCurrentTag(state, id:string) {
      state.currentTag = state.tagList.find(t => t.id === id)
    },
  },
})

export default store

TS中的computed使用getter/setter语法

如果在@Component中使用computed,发现在