傳統 Vuex 都以 this
使用,這使得 Extract Function 時還必須將 Vue Instance 傳進 Function,事實上 Vuex 也能不使用 this
,直接 Import Store 使用,甚至更近一步 Point-free。
Version
Vue 2.6.11
Vuex 3.4.0
Options API
使用 Vuex 實現 counter。
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let addCount = state => state.count++
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
addCount
}
})
第 9 行
state: {
count: 0
},
定義 count
state 初始值為 0
。
第 6 行
let addCount = state => state.count++
定義 addCount
mutation,每次呼叫都對 count
state 遞增。
App.vue
<template>
<div>
<button @click="onClick">+</button>
{{ count }}
</div>
</template>
<script>
let count = function() {
return this.$store.state.count
}
let onClick = function() {
this.$store.commit('addCount')
}
export default {
name: 'App',
computed: {
count
},
methods: {
onClick
}
}
</script>
第 9 行
let count = function() {
return this.$store.state.count
}
使用 count
computed 處理 count
state,當 count
state 改變時,count
computed 會隨之 reactive 改變。
傳統會使用 this.$store
讀取 Vuex,由與使用了 this
,必須使用 function expression 而不能使用 arrow function,也不方便 extract function。
13 行
let onClick = function() {
this.$store.commit('addCount')
}
使用 this.$store
的 commit()
呼叫 addCount
mutation,由於使用了 this
,必須使用 function expression 而不能使用 arrow function,也不方便 extract function。
Functional API
App.vue
<template>
<div>
<button @click="onClick">+</button>
{{ count }}
</div>
</template>
<script>
import store from '@/store'
let count = () => store.state.count
let onClick = () => store.commit('addCount')
export default {
name: 'App',
computed: {
count
},
methods: {
onClick
}
}
</script>
第 9 行
import store from '@/store'
將實際 store 引入。
11 行
let count = () => store.state.count
直接以 store
使用 Vuex,由其下的 state
讀取 count
state。
因為不再使用 this
,因此可安心使用 arrow function。
13 行
let onClick = () => store.commit('addCount')
直接以 store
使用 Vuex,將 addCount
mutation 傳入 commit()
執行之。
因為不再使用 this
,因此可安心使用 arrow function。
Point-free
App.vue
<template>
<div>
<button @click="onClick">+</button>
{{ count }}
</div>
</template>
<script>
import { pipe, always, prop } from 'ramda'
import store from '@/store'
let { state, commit } = store
let count = pipe(
always(state),
prop('count')
)
let onClick = pipe(
always('addCount'),
commit
)
export default {
name: 'App',
computed: {
count
},
methods: {
onClick
}
}
</script>
12 行
let { state, commit } = store
從 store
直接 destructure 出 state
與 commit()
。
14 行
let count = pipe(
always(state),
prop('count')
)
- 使用
prop()
讀取state.count
,先透過always()
準備state
19 行
let onClick = pipe(
always('addCount'),
commit
)
- 使用
commit()
執行 mutation,先透過always()
準備addCount
Conclusion
- Vue 有多種寫法,其實不見得什麼都要使用
this
,Vuex 透過引用實際 store 可直接使用,不用再擔心很難處理this
- 既然不必使用
this
,可直接 destructure 出state
與commit()
,進一步使用 Function Pipeline 組合