如何使用Vuex管理Vue的状态
Vue和Vuex的连接方法想要总结一下:
一般来说Vue和Vuex都存在一下基础文件,
首先是store
stores/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const state = { familyName: '', givenName: '', }
const mutations = { setFamilyName (state, val) { state.familyName = val }, setGivenName (state, val) { state.givenName = val }, }
const getters = { fullName: (state) => { return `${state.familyName}${state.givenName}` } }
const actions = {}
export default new Vuex.Store({ state, mutations, getters, actions, })
|
如何从Vue向Vuex传值
方法1.使用Vue.js的监视属性(watched propery)
如果使用watch的话,想通过别的值来改变目标值的时候,就不太灵活了。所以其实不是很推荐。
template
1
| <input type="text" name="familyName" v-model="familyName">
|
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import Vue from 'vue' import Vuex from 'vuex'
import store from './stores'
new Vue({ el: "#app", state: { familyName: '', givenName: '', }, watch: { familyName (val) { store.commit('setFamilyName', val) }, }, })
|
方法2: 通过事件传递值,并在Vue的方法里commit
首先还是一样的template
1
| <input type="text" name="familyName" @input="setFamilyName">
|
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import Vue from 'vue' import Vuex from 'vuex'
import store from './stores'
new Vue({ el: "#app", state: {}, watch: {}, methods: { setFamilyName (e) { store.commit('setFamilyName', e.target.value) }, }, })
|
方法4: 通过事件传递,通过store的action进行commit
首先是Vue的template, 这里给方法指定参数的话有多种方法。
1 2 3
| <input type="text" name="familyName" @input="updateFamilyName"> <!-- or --> <input type="text" name="familyName" @input="updateFamilyName($event.target.value)">
|
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import Vue from 'vue' import Vuex from 'vuex' import { mapActions } from 'vuex'
import store from './stores'
new Vue({ el: "#app", store, state: {}, watch: {}, methods: { ...mapActions([ 'updateFamilyName', ]), }, })
|
stores/index.js
1 2 3 4 5 6 7 8 9 10
| const actions = { updateFamilyName({ commit, state }, e) { commit('setFamilyName', e.target.value) }, }
|
方法4:使用get和set进行双向绑定
参考Vue公式
vue里使用v-model并在Vue.js的computed属性里定义set。
最好顺便定义好get,如果没有定义好get的情况下,mapState有可能会无法正常工作。
不想使用watched property进行监视并对store里的值进行更新的情况下v-model就显得很方便了。
首先还是template
1
| <input type="text" name="familyName" v-model="familyName">
|
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import Vue from 'vue' import Vuex from 'vuex'
import store from './stores'
new Vue({ el: "#app", state: {}, computed: { familyName: { get () { return store.state.familyName }, set (val) { store.commit('setFamilyName', val) }, }, }, })
|
究竟那种方法更好?
在vue的官方公式网站上说state应该是由action通过mutaion来进行改变。
而不是在Vue的methods里进行store.commit。
但是在Vue的初级入门的例子里其实是存在通过methods来commit的。
所以按情况来说,直接通过action来改变state的状态也不是不可以/
在非同期的处理的时候, 可以直接通过action进行commit,
但是只是对store的情况下,可以考虑直接从Vue里commit。
如何从Vuex向Vue传值
方法1: 活用computed
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import Vue from 'vue' import Vuex from 'vuex'
import store from './stores'
new Vue({ el: "#app", ・・・(略)・・・ computed: { familyName() { return store.state.familyName }, givenName() { return store.state.givenName }, firstName () { return store.state.givenName }, fullName () { return store.getters.fullName }, } ・・・(略)・・・ }
|
方法2: 使用mapState和mapGetters
通过数组的形式定义好store的key
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { mapState, mapGetters } from 'vuex' import store from './stores'
new Vue({ el: "#app", store, ・・・(略)・・・ computed: { ...mapState([ 'familyName', 'givenName', ]), ...mapState({ firstName: 'givenName' }), ...mapGetters([ 'fullName' ]), } ・・・(略)・・・ }
|
方法3: 在store里使用其他的getters
比如familyName
和givenName
里不存在半角空格和不正确的字符的情况下显示kana,
首先在getters里定义好判断familyName
和givenName
是否为valid的方法,
两个条件同时满足的时候显示kana。
getters方法里如果第二参数是getters的话可以直接调用其他的getters里的方法。
stores/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13
| const getters = { ・・・(略)・・・ isValidFamilyName: (state) => { return String(state.familyName).trim() !== '' }, isValidGivenName: (state) => { return String(state.givenName).trim() !== '' }, isVisibleKana: (state, getters) => { return getters.isValidFamilyName && getters.isValidGivenName }, ・・・(略)・・・ }
|
最终效果
familyName、givenName用的是方法4追加进store
familyNameKana、givenNameKana是用方法3。
index.html
1 2 3 4 5 6 7 8 9 10 11
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>vuejs-vuex-simple-sample</title> </head> <body> <div id="app"></div> </body> </html>
|
main.js
1 2 3 4 5 6 7 8 9 10 11 12
| import Vue from 'vue' import App from './App'
Vue.config.productionTip = false
new Vue({ el: '#app', components: { App, }, template: '<App/>', })
|
App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <template> <div id="app"> <div> 名前:<input type="text" name="familyName" v-model="familyName"> <input type="text" name="givenName" v-model="givenName"> </div> <div>フルネーム:{{ fullName }}</div> <div>firstName:{{ firstName }}</div>
<div v-show="isVisibleKana"> ナマエ:<input type="text" name="familyNameKana" @input="updateFamilyNameKana"> <input type="text" name="givenNameKana" @input="updateGivenNameKana"> </div> <div v-show="isVisibleKana">フルネーム(カナ):{{ fullNameKana }}</div> </div> </template>
<script> import Vue from 'vue' import Vuex from 'vuex' import { mapState, mapGetters, mapActions } from 'vuex'
import store from './stores'
Vue.use(Vuex)
export default { name: 'App', store, computed: { familyName: { get () { return store.state.familyName }, set (val) { store.commit('setFamilyName', val) }, }, givenName: { get () { return store.state.givenName }, set (val) { store.commit('setGivenName', val) }, }, ...mapState({ firstName: 'givenName', }), ...mapGetters([ 'fullName', 'isVisibleKana', 'fullNameKana', ]), }, methods: { ...mapActions([ 'updateFamilyNameKana', 'updateGivenNameKana', ]), }, } </script>
|
stores/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const state = { familyName: '', givenName: '', familyNameKana: '', givenNameKana: '', }
const mutations = { setFamilyName (state, val) { state.familyName = val }, setGivenName (state, val) { state.givenName = val }, setFamilyNameKana (state, val) { state.familyNameKana = val }, setGivenNameKana (state, val) { state.givenNameKana = val }, }
const getters = { fullName: (state) => { return `${state.familyName}${state.givenName}` }, isValidFamilyName: (state) => { return String(state.familyName).trim() !== '' }, isValidGivenName: (state) => { return String(state.givenName).trim() !== '' }, isVisibleKana: (state, getters) => { return getters.isValidFamilyName && getters.isValidGivenName }, fullNameKana: (state) => { return `${state.familyNameKana}${state.givenNameKana}` }, }
const actions = { updateFamilyNameKana ({ commit, state }, e) { commit('setFamilyNameKana', e.target.value) }, updateGivenNameKana ({ commit, state }, e) { commit('setGivenNameKana', e.target.value) }, }
export default new Vuex.Store({ state, mutations, getters, actions, })
|