一个简单案例教你如何用Typescript写Vuex
案例源代碼: github.com/danielhuoo/…
前言
相信很多人都像我一樣,學(xué)習(xí)使用了vuex后,想把項(xiàng)目改寫(xiě)成Typescript。但是官方教程要么晦澀難懂,要么缺少鮮活的例子。我花了一天時(shí)間,總結(jié)出了一些經(jīng)驗(yàn)。在此分享出來(lái)。
本教程通過(guò)編寫(xiě)一個(gè)簡(jiǎn)單的demo講解vuex的實(shí)現(xiàn)方式,以及如何對(duì)基于vue2.x的已有項(xiàng)目進(jìn)行Typescript重構(gòu)。
項(xiàng)目初始化
現(xiàn)在都9012了,所以我們直接使用vue-cli 3.x快速搭建系統(tǒng)。
# 搭建項(xiàng)目 vue create vue2.x-vuex-typescript-democd vue2.x-vuex-typescript-demo # 引入vuex vue add vuex # 由于我實(shí)在不想寫(xiě)任何樣式,所以我又加一個(gè)element vue add element 復(fù)制代碼模塊說(shuō)明
為了用實(shí)際的代碼解釋vuex是如何搭建的,以及模塊間的通訊方式,我用了一個(gè)很淺顯的例子(應(yīng)該比官方的例子明朗很多)
情景
男孩給女孩送花。
目錄結(jié)構(gòu)
你會(huì)發(fā)現(xiàn)默認(rèn)的目錄結(jié)構(gòu)是這樣的:
. ├── 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但是我們想讓vuex變得模塊化。所以我們改成以下的結(jié)構(gòu):
. ├── 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模塊定義
boy.js
該模塊定義了三個(gè)action方法。action通俗來(lái)說(shuō)就是你想讓模塊做的事情,它們可以是異步或者同步的。所有對(duì)state的增刪查改的邏輯都應(yīng)該在這里,而mutation僅僅負(fù)責(zé)執(zhí)行增刪查改。
import { Message } from 'element-ui'; export default {namespaced: true,// state 的屬性只能通過(guò) mutation的方法進(jìn)行修改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: {// 送花// 方法里 調(diào)用了 commit 和 state,需要在傳參時(shí)聲明sendFlower({ commit, state }, params) {if (!state.currentFlower) {Message({showClose: true,message: "沒(méi)花可送了",type: "warning"});} else {// 送出一朵花,自己的庫(kù)存減 1commit('updateCurrentFlower', -params.sendNumber)// 女孩收到一朵花,女孩庫(kù)存加 1。// 注意這里是跨模塊調(diào)用,所以需要加上模塊前綴 'girl/',并且 傳入?yún)?shù) {root:true} 表明通過(guò)根路徑尋找目標(biāo)函數(shù)。commit('girl/updateCurrentFlower', params.sendNumber, { root: true })}},// 受到鼓勵(lì)beEncouraged({ commit }) {commit('updateBraveScore', { score: 10 })},// 買(mǎi)花// 方法里調(diào)用了 commit, dispatch。 dispatch跨模塊調(diào)用根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: "庫(kù)存不足",type: "warning"});})}, 100)}} } 復(fù)制代碼girl.js
export default {namespaced: true,state: {currentFlower: 0},mutations: {updateCurrentFlower(state, payload) {state.currentFlower = state.currentFlower + payload}},actions: {// 對(duì)男孩進(jìn)行鼓舞encourage({ dispatch }, params) {dispatch('boy/beEncouraged', null, { root: true })}} } 復(fù)制代碼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({// 根 statestate: {flowersInStock: 10},// 根 mutationsmutations: {updateFlowersInStock(state, payload) {state.flowersInStock = state.flowersInStock + payload}},// 根 actionsactions: {sellFlower({ commit, state }, params) {return new Promise((resolve, reject) => {if (state.flowersInStock > 0) {commit('updateFlowersInStock', -1)resolve()} else {reject()}})}},// 注冊(cè)模塊modules: {boy,girl} }) 復(fù)制代碼連接到vue組件
現(xiàn)在倉(cāng)庫(kù)的邏輯已經(jīng)寫(xiě)好了,我們就可以在組件上使用了。實(shí)際上vuex倉(cāng)庫(kù)早在main.js被引入了vue實(shí)例里了。例如,this.$store.state.flowersInStock即代表根state的屬性值。但是這種寫(xiě)法太過(guò)繁瑣,我們引入了vuex提供的 mapState、mapActions 和 mapMutations 進(jìn)行映射。
boy.vue
<template><div><div>男孩</div><div>手上有{{currentFlower}}朵花</div><div><el-button @click="sendFlower({sendNumber:1})">送花</el-button><el-button @click="buyFlower({buyNumber:1})">買(mǎi)花</el-button></div><div>勇氣值:{{braveScore}}</div></div> </template> <script> import { mapState, mapActions } from "vuex"; export default {computed: {// 你會(huì)發(fā)現(xiàn)state的映射放在了computed里面。這么做的好處是由于 Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的,從 store 實(shí)例中讀取狀態(tài)最簡(jiǎn)單的方法就是在計(jì)算屬性中返回某個(gè)狀態(tài)。// 通過(guò)映射,this.$store.state.currentFlower 就可以表示為 this.currentFlower...mapState("boy", {currentFlower: state => state.currentFlower,braveScore: state => state.braveScore})},methods: {// actions 放在了methods里面。這不奇怪,因?yàn)閍ctions跟mutations一樣,都是vuex里面的方法。...mapActions("boy", ["sendFlower", "buyFlower"])} }; </script> <style> </style> 復(fù)制代碼很多人在剛開(kāi)始用vuex都會(huì)記不住,究竟state、actions和mutations放哪里。其實(shí)很好記:
- state是屬性,放computed里。
- actions和mutations是方法,放methods里。
girl.vue 同理,就不贅述了。下一步,我們開(kāi)始用Typescript改寫(xiě)代碼。
安裝Typescript
在安裝之前,請(qǐng)一定要先做備份。因?yàn)榘惭b后App.vue會(huì)被改寫(xiě)。
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 復(fù)制代碼改寫(xiě)開(kāi)始
你會(huì)發(fā)現(xiàn)所有.js文件都被改成.ts后綴了。這時(shí)候整個(gè)項(xiàng)目是跑不起來(lái)的。命令行控制臺(tái)會(huì)爆出幾十個(gè)error。事實(shí)上,在你沒(méi)有把所有該改的地方改好之前,項(xiàng)目是不會(huì)跑通的。
index.ts
被改寫(xiě)的地方:
- 引入module的方式。改為import對(duì)象中的一個(gè)屬性
- 定義了store的類(lèi)別。
- 新增了一個(gè)RootState。
root-types.ts
這是對(duì)根state的約束
export interface RootState {flowersInStock: number } 復(fù)制代碼boy.ts
模塊的改動(dòng)是巨大的。
- 新增了模塊的State接口
- 定義mutations的類(lèi)為 MutationTree
- 定義actions的類(lèi)為 ActionTree
- 定義模塊的類(lèi)為 Module
boy.vue
vue文件改動(dòng)的地方也是很多的:
- script標(biāo)簽指定了ts語(yǔ)言
- 使用Component修飾組件
- export 組件 從 對(duì)象變?yōu)?類(lèi)
- 棄用 mapState 等方法,使用 State、Action、Mutation 修飾器綁定 vuex
- 棄用computed、methods、data 等寫(xiě)法,使用get + 方法表示 computed,methods里的方法直接被抽出來(lái),data的屬性直接被抽出來(lái)。
其他文件也是用類(lèi)似的方法去改寫(xiě)。換湯不換藥。
以上就是Typescript改寫(xiě)的例子。有些地方?jīng)]有解釋得很清楚,因?yàn)槲乙彩且粋€(gè)小白啊,不懂的地方還是不要誤導(dǎo)大家了。如果你的項(xiàng)目的邏輯比這個(gè)更復(fù)雜(肯定吧),而本項(xiàng)目沒(méi)有覆蓋到你的疑惑,你可以去看我的另一個(gè)改好的項(xiàng)目Jessic。
- 作者:Daniel Huo
- 鏈接:danielhuoo.github.io/2019/06/18/…
- 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
轉(zhuǎn)載于:https://juejin.im/post/5d09682d518825531e0648a7
總結(jié)
以上是生活随笔為你收集整理的一个简单案例教你如何用Typescript写Vuex的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 这是一个神奇的文字转语音软件
- 下一篇: Gamma阶段测试报告