全局管理之Vuex
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。
我们之前在store/index2.ts
里自己定义的store对象,就是管理了所有组件共用的数据和操作数据的API。
这个Vuex就是一个这样的store。
我们在创建项目时,自动引入了Vuex。可以看到在store/index.ts里自动有了这些
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { }, mutations: { }, actions: { }, modules: { } })
而且在入口文件main.ts里,自动在Vue实例里创建好了
import store from './store'; new Vue({ router: router, store, render: h => h(App) }).$mount('#app');
(如果要单独使用时,一定要import,并且在选项里引入store)
一. Vuex的简单使用
我们先在项目提供好的store/index.ts里修改
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store= new Vuex.Store({ state: { count:0 }, mutations: { increment(state,n){ state.count+=n } }, }) console.log(store.state.count); store.commit('increment',10) console.log(store.state.count); export default store;
- 声明一个store实例,它有一些构造选项,像new Vue一样。然后导出这个store。
- 数据写在
state
对象里(类似Vue里的data)。使用:store.state.count
- 操作数据的方法,写在
mutations
对象里(类似Vue里的methods)。如果这个函数要访问state里的数据,Vuex自动给他传了一个参数state
- 调用store里的方法:
store.commit('increment')
Vuex里不提供this
其实就是state,mutations,commit的概念,只不过换了另一种形式
二. 在Vue组件中使用store
//Money.vue <template> {{count}} <button @click="add">+1</button> </template> <script lang="ts"> import store from '@/store/index.ts'; @Component({ computed:{ count(){ return store.state.count } } }) export default class Money extends Vue{ add(){ store.commit('increment') } } </script>
首先导入文件里的store。数据要定义成计算属性,不能是data。因为data只会在第一次获取,而computed会依赖store里的数据的变化,重新计算。
因为在template里访问不到引入的store,所以方法一是在自己的方法里,调用store的方法。
方法2:this.$store
//Money.vue <template> {{count}} <button @click="$store.commit('increment')">+1</button> </template> <script lang="ts"> import store from '@/store/index.ts'; @Component({ computed:{ count(){ return store.state.count } } }) export default class Money extends Vue{ } </script>
可以在template里,直接访问到$store
,进而就可以调用它的方法。
原理:
这个$store
其实是this.$store
,因为在template里可以不写this。
那么this.$store
又是从哪来的呢?
在index.ts里有一句:Vue.use(Vuex)
,它会把store绑到Vue的原型上。所以Vue实例/组件就可以访问store。而Vue实例/组件也就是this。使用:this.$store
同时,因为在入口文件main.ts里已经自动引入了store,所以在组件里使用时不需要引入了。直接使用this.$store即可
注意
1.
mutations
里定义的方法是没有返回值的,不能写return,写了外边调用的时候也拿不到返回值。 只能单纯的操作,不能return
如果有需要调用mutations
里的API,并且要它的返回值,把返回值赋给自己组件上的data时,目的是把返回值赋给自己的一个数据。
那么可以在state里声明一个数据,这个API里把return 一个返回值改成进行某种操作后,把得到的值赋给state里的这个数据。
然后在组件里,让自己的数据成为计算属性,return state里的数据。
2. 在ts里使用计算属性要用getter语法
<script lang="ts"> import Vue from 'vue'; import {Component} from 'vue-property-decorator'; @Component({ computed:{ tag(){ return this.$store.state.currentTag } } }) export default class EditLabel extends Vue { created(){ const id=this.$route.params.id this.$store.commit('findTag',id) if(!this.tag){ this.$router.replace('/404') } }
如果这样写,在ts里使用计算属性this.tag
时会报错,说TS2339: Property 'tag' does not exist on type 'EditLabel'.
可是我们明明声明了,怎么会不存在呢。
之前我们使用计算属性从store里拿到tagList和recordList,没有在ts里用,而是在template里用作展示或循环之类的,所以没有报错。
这可能是因为ts和Vue不配合引起的。
解决方法:使用getter语法
export default class EditLabel extends Vue { get tag(){ return this.$store.state.currentTag }
去掉computed对象,改使用get函数。这样在ts里用this.tag就不报错了。 vue class component 写的计算属性的方法
3. mutations里的函数的参数最多两个
在mutations里定义的函数,通常Vuex会自动给传一个state参数。(但是要自己写出来,在参数列表里)如果还需要别的参数,加上state最多只能有两个。如果超过了会报错。
当多个组件的选项有重复时,可以使用mixins选项,把重复的放到混入对象里。
那么TS写法的mixins的语法是什么样的呢?
混入对象的声明
作为对比,在JS里可以直接在创建的文件里导出一个对象,对象里就是组件们都要用到的选项。
在TS里,比如我们在/mixins/tagHelper.ts
文件里声明:
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){ window.alert('标签名不能为空') }else{ this.$store.commit('createTag',name) } } }
在Vue组件里使用
<script lang="ts"> import {Component} from 'vue-property-decorator'; import {tagHelper} from '@/mixins/tagHelper'; import {mixins} from 'vue-class-component'; @Component({ components: {Button}, computed:{ tags(){ return this.$store.state.tagList } } }) export default class Labels extends mixins(tagHelper) { } </script>
- 原来extends Vue。 使用mixins就需要
extends mixins(tagHelper)
,括号里边的是定义的文件名。 - 导入mixins,导入声明了混入对象的文件
然后在组件里就可以使用createTag方法了。这是js里的methods里的方法。ts里可以不用写methods。
ts里,计算属性是写到@Compontent
里