Case Source: github.com/danielhuoo/...
Foreword
I believe many people like me, learning to use the vuex
post, trying to rewrite the project Typescript
. But the official tutorial either obscure or lack vivid example. I spent a day, summed up some experience. In this sharing out.
This tutorial by writing a simple demo to explain the vuex
implementation of, and how based on vue2.x
existing projects were Typescript reconstruction.
Project Initialization
9012 now, so we used directly vue-cli 3.x quickly build systems.
# 搭建项目
vue create vue2.x-vuex-typescript-demo
cd vue2.x-vuex-typescript-demo
# 引入vuex
vue add vuex
# 由于我实在不想写任何样式,所以我又加一个element
vue add element
复制代码
Module Description
In order to explain the actual code vuex
is how to build, as well as communication between modules, I used a very simple example (the example should be a lot clearer than the official)
scene
Boy to girl flowers.
- Each boy took out 10 girls express gratitude.
- Girls will increase thanks to the courage of the boy's value.
- The boy can buy flowers to the flower shop.
Directory Structure
You will find the default directory structure is as follows:
. ├── README.md ├── babel.config.js ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── HelloWorld.vue │ ├── main.js │ ├── plugins │ │ └── element.js │ └── store.js └── yarn.lock
But we want vuex become modular. So we changed to the following structure:
. ├── README.md ├── babel.config.js ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── HelloWorld.vue │ ├── main.js │ ├── plugins │ │ └── element.js │ └── store │ ├── index.js │ └── module │ ├── boy.js │ └── girl.js └── yarn.lock
index.js
It is thestore
main file/module
Under storage module file.boy.js
Module is a boy,girl.js
a girl Module
Module Definition
boy.js
The module defines three action
methods. action
Popular, what you want to do things module, they can be asynchronous or synchronous. All of the state
additions and deletions to change the logic of the investigation should be here, but mutation
merely responsible for implementing the additions and deletions to change search.
import { Message } from 'element-ui';
export default {
namespaced: true,
// state 的属性只能通过 mutation的方法进行修改
state: {
currentFlower: 50,
braveScore: 0
},
mutations: {
// 修改 state 的 currentFlower 的值
updateCurrentFlower(state, payload) {
state.currentFlower = state.currentFlower + payload
},
// 修改 state 的 braveScore 的值
updateBraveScore(state, payload) {
state.braveScore = state.braveScore + payload.score
}
},
actions: {
// 送花
// 方法里 调用了 commit 和 state,需要在传参时声明
sendFlower({ commit, state }, params) {
if (!state.currentFlower) {
Message({
showClose: true,
message: "没花可送了",
type: "warning"
});
} else {
// 送出一朵花,自己的库存减 1
commit('updateCurrentFlower', -params.sendNumber)
// 女孩收到一朵花,女孩库存加 1。
// 注意这里是跨模块调用,所以需要加上模块前缀 'girl/',并且 传入参数 {root:true} 表明通过根路径寻找目标函数。
commit('girl/updateCurrentFlower', params.sendNumber, { root: true })
}
},
// 受到鼓励
beEncouraged({ commit }) {
commit('updateBraveScore', { score: 10 })
},
// 买花
// 方法里调用了 commit, dispatch。 dispatch跨模块调用根store的action,跟送花的commit一样,需要加上前缀和传入{root:true}
buyFlower({ commit, dispatch }, params) {
setTimeout(() => {
dispatch('sellFlower', null, { root: true }).then(() => {
commit('updateCurrentFlower', params.buyNumber)
}).catch(() => {
Message({
showClose: true,
message: "库存不足",
type: "warning"
});
})
}, 100)
}
}
}
复制代码
girl.js
export default {
namespaced: true,
state: {
currentFlower: 0
},
mutations: {
updateCurrentFlower(state, payload) {
state.currentFlower = state.currentFlower + payload
}
},
actions: {
// 对男孩进行鼓舞
encourage({ dispatch }, params) {
dispatch('boy/beEncouraged', null, { root: true })
}
}
}
复制代码
index.js
import Vue from 'vue'
import Vuex from 'vuex'
// 引入模块
import boy from './module/boy'
import girl from './module/girl'
Vue.use(Vuex)
export default new Vuex.Store({
// 根 state
state: {
flowersInStock: 10
},
// 根 mutations
mutations: {
updateFlowersInStock(state, payload) {
state.flowersInStock = state.flowersInStock + payload
}
},
// 根 actions
actions: {
sellFlower({ commit, state }, params) {
return new Promise((resolve, reject) => {
if (state.flowersInStock > 0) {
commit('updateFlowersInStock', -1)
resolve()
} else {
reject()
}
})
}
},
// 注册模块
modules: {
boy,
girl
}
})
复制代码
Connected to the assembly vue
Now logic warehouse has been written, we can use on the component. In fact vuex
the warehouse as early as main.js
the introduction of the vue
examples in the. For example, this.$store.state.flowersInStock
which represents the root state
property values. But such an approach is too cumbersome, we introduced the vuex
offer mapState
, mapActions
and mapMutations
mapping.
boy.vue
<template>
<div>
<div>男孩</div>
<div>手上有{{currentFlower}}朵花</div>
<div>
<el-button @click="sendFlower({sendNumber:1})">送花</el-button>
<el-button @click="buyFlower({buyNumber:1})">买花</el-button>
</div>
<div>勇气值:{{braveScore}}</div>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
export default {
computed: {
// 你会发现state的映射放在了computed里面。这么做的好处是由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态。
// 通过映射,this.$store.state.currentFlower 就可以表示为 this.currentFlower
...mapState("boy", {
currentFlower: state => state.currentFlower,
braveScore: state => state.braveScore
})
},
methods: {
// actions 放在了methods里面。这不奇怪,因为actions跟mutations一样,都是vuex里面的方法。
...mapActions("boy", ["sendFlower", "buyFlower"])
}
};
</script>
<style>
</style>
复制代码
A lot of people used in the beginning vuex
will not remember, what state
, actions
and mutations
where to put. In fact, easy to remember:
state
It is a property, putcomputed
in.actions
Andmutations
is a method, putmethods
inside.
girl.vue
Similarly, we do not go into details. Next, we began Typescript
to rewrite the code.
installationTypescript
Before installing, make sure to do first backup. Because the installation App.vue
will be overwritten.
yarn add vuex-class
vue add typescript
? Use class-style component syntax? (Y/n) Yes
? Use Babel alongside TypeScript for auto-detected polyfills? (Y/n) Yes
复制代码
Rewrite start
You will find all the .js
files have been changed to .ts
the suffix a. This time the project is not run up. Command line console broke dozens error
. In fact, before you do not have all the parts of the reform changing for the better, the project is not going to run through.
index.ts
Local rewritten:
- The introduction of
module
the way. Toimport
a property of the object - It defines the
store
category. - Added a
RootState
.
import Vue from 'vue'
import Vuex, { StoreOptions } from 'vuex'
import { boy } from './module/boy'
import { girl } from './module/girl'
import { RootState } from './root-types';
Vue.use(Vuex)
const store: StoreOptions<RootState> = {
// 里面的内容不用修改
state: {
flowersInStock: 10
},
modules: {
boy,
girl
},
mutations: {
updateFlowersInStock(state, payload) {
state.flowersInStock = state.flowersInStock + payload
}
},
actions: {
sellFlower({ commit, state }) {
return new Promise((resolve, reject) => {
if (state.flowersInStock > 0) {
commit('updateFlowersInStock', -1)
resolve()
} else {
reject()
}
})
}
}
}
export default new Vuex.Store<RootState>(store)
复制代码
root-types.ts
This is the root of state
constraints
export interface RootState {
flowersInStock: number
}
复制代码
boy.ts
The module is a huge change.
- Added module
State
interfaces - The definition
mutations
of classMutationTree
- The definition
actions
of classActionTree
- Class definition module is
Module
import { Message } from 'element-ui';
import { BoyState } from './module-types';
import { MutationTree, ActionTree, Module } from 'vuex';
import { RootState } from '../root-types';
const state: BoyState = {
currentFlower: 50,
braveScore: 0
}
// 传入的泛型可以通过查看源代码得知。
const mutations: MutationTree<BoyState> = {
updateCurrentFlower(state, payload) {
state.currentFlower = state.currentFlower + payload
},
updateBraveScore(state, payload) {
state.braveScore = state.braveScore + payload.score
}
}
const actions: ActionTree<BoyState, RootState> = {
sendFlower({ commit, state }, params) {
if (!state.currentFlower) {
Message({
showClose: true,
message: "没花可送了",
type: "warning"
});
} else {
commit('updateCurrentFlower', -params.sendNumber)
commit('girl/updateCurrentFlower', params.sendNumber, { root: true })
}
},
buyFlower({ commit, dispatch }, params) {
setTimeout(() => {
dispatch('sellFlower', null, { root: true }).then(() => {
commit('updateCurrentFlower', params.buyNumber)
}).catch(() => {
Message({
showClose: true,
message: "库存不足",
type: "warning"
});
})
}, 100)
},
beEncouraged({ commit }) {
commit('updateBraveScore', { score: 10 })
}
}
export const boy: Module<BoyState, RootState> = {
namespaced: true,
state,
mutations,
actions
}
复制代码
boy.vue
vue
File is a lot of place changes:
script
Tag specifies thets
language- The use of
Component
modified components export
Class component from the object becomes- Abandoned
mapState
and other methods, useState
,Action
,Mutation
decorator bindingvuex
- Abandoned
computed
,methods
,data
and other written, usingget + 方法
expressedcomputed
,methods
in the method of directly extracted, thedata
attribute to be extracted directly.
<script lang="ts">
import { Vue, Component, Watch } from "vue-property-decorator";
import { State, Action, Mutation, namespace } from "vuex-class";
import { BoyState } from "../store/module/module-types";
@Component
export default class boyComponent extends Vue {
@State("boy")
// 感叹号不能省略
boyState!: BoyState;
@Action("sendFlower", { namespace: "boy" })
sendFlower: any;
@Action("buyFlower", { namespace: "boy" })
buyFlower: any;
get currentFlower(): number {
return this.boyState.currentFlower;
}
get braveScore(): number {
return this.boyState.braveScore;
}
}
</script>
复制代码
Other files are also in a similar way to rewrite. A new name.
Above is Typescript
an example of rewriting. Some places did not explain very clearly, because I am also a white ah, do not know where or not to mislead people. If the logic of your project is more complex than this (sure it), but this project does not cover your doubts, you can change a good look at my other projects Jessic .
- Author: Daniel Huo
- Links: danielhuoo.github.io/2019/06/18/...
- Copyright reserved by the authors. Commercial reprint please contact the author authorized, non-commercial reprint please indicate the source.
Reproduced in: https: //juejin.im/post/5d09682d518825531e0648a7