什麼是Vuex,這裏就不介紹了,請移步到官網 vuex.vuejs.org/zh/guide/ 學習,這裏咱們只須要知道Vuex能夠用來作應用的狀態管理。 首先來看一下使用vue create my-project命令生成項目的時候,自動生成的Vuex的代碼,store.js:vue
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
}
})
複製代碼
下面咱們來搞懂模版代碼中的state,mutations,actions是幹嗎的,既然Vuex能夠用來作狀態管理,那麼管理的是什麼?咱們知道vue是mvvm架構,想到mvvm 咱們就是想到數據驅動ui,因此,狀態管理,說白了管理的就是數據,那麼咱們就能夠把咱們須要操控的數據放在state裏面vuex
狀態,也就是存放咱們須要操控的數據數組
改變,若是咱們須要改變state中的數據的時候能夠在這裏面操做,怎麼操做?下面說bash
行爲,和mutations相似,咱們想要改變state中的數據的時候能夠在這裏面進行操做,一樣,怎麼操做,下面說架構
既然是狀態管理,若是咱們直接操做state去改變他的值的話,固然就稱不上管理,Vuex採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化 ,固然不會直接讓咱們去修改state裏面的值。若是想要改變狀態的值怎麼辦,mutations登場:異步
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
userInfo: {}
},
mutations: {
setUserInfo(state) {
let info = {
name: 'wfq',
age: 26
}
state.userInfo = info
}
},
actions: {}
})
複製代碼
而後在咱們的頁面上,咱們能夠這樣使用:mvvm
<template>
<div>
<div>name:{{$store.state.userInfo.name}}</div>
<el-button type="primary" size="small" @click="$store.commit('setUserInfo')">獲取用戶信息</el-button>
</div>
</template>
<script>
export default {
name: "vuex1",
data() {
return {}
},
methods: {},
mounted() {
}
}
</script>
<style scoped>
</style>
複製代碼
使用$store.commit('setUserInfo')來觸發mutations中的getUserInfo方法,對於mutations,這裏有幾點須要注意:ide
多個 state 的操做 , 使用 mutations 會來觸發會比較好維護 , 那麼須要執行多個 mutations怎麼辦?actions登場,前面說過 官方建議咱們在actions裏面寫異步的代碼,那麼咱們模擬一下:函數
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
userInfo: {}
},
mutations: {
setUserInfo(state,userInfo) {
state.userInfo = userInfo
}
},
actions: {
// commit來自Vuex中上下文context,這裏直接使用對象解構,至關於context.commit('setUserInfoAsync',info)
setUserInfoAsync({commit}){
setTimeout(()=>{
let info = {
name: 'wfq',
age: 26
}
commit('setUserInfo',info)
},2000)
}
}
})
複製代碼
在store.js中咱們在actions中使用commit來觸發mutations裏面的方法,這個和上面說的一致,那麼咱們怎麼觸發actions裏面的方法:學習
<template>
<div>
<div>name:{{$store.state.userInfo.name}}</div>
<el-button type="primary" size="small" @click="$store.dispatch('setUserInfoAsync')">獲取用戶信息</el-button>
</div>
</template>
複製代碼
咱們使用dispatch來觸發actions裏面的方法。
若是咱們調用方法,頁面上過分使用this.$store.***的話,會顯得很累贅,上面三個函數即是Vuex給咱們提供的函數,方便咱們調用store裏面的方法 首先記住一點,mapstate和mapGetters放在computed中,mapActions放在methods,記得導入mapState,mapGetters,mapActions,那麼咱們以前頁面的代碼能夠改寫以下:
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
userInfo: {}
},
getters:{
getUserInfo(state){
return state.userInfo
}
},
mutations: {
setUserInfo(state,userInfo) {
state.userInfo = userInfo
}
},
actions: {
// commit來自Vuex中上下文context,這裏直接使用對象解構,至關於context.commit('setUserInfoAsync',info)
setUserInfoAsync({commit}){
setTimeout(()=>{
let info = {
name: 'wfq',
age: 26
}
commit('setUserInfo',info)
},2000)
}
}
})
複製代碼
頁面
<template>
<div>
<div>name:{{userInfo.name}}</div>
<el-button type="primary" size="small" @click="getInfo">獲取用戶信息</el-button>
</div>
</template>
<script>
import {mapState,mapGetters,mapActions} from 'vuex'
export default {
name: "vuex1",
data() {
return {}
},
computed:{
// 這裏的mapState對應store.js裏面的state,參數是個數組,裏面的元素其實就是store.js裏面的state裏面的數據
...mapState([
'userInfo'
]),
// 這裏的mapGetters對應store.js裏面的getters,參數是個數組,裏面的元素其實就是store.js裏面的getters裏面的方法
// mapGetters其實和mapState相似,都是獲取state裏面的數據,大多數狀況,咱們使用mapState便可,這也是爲何state.js的
// 模版代碼中沒有getters
...mapGetters([
'getUserInfo'
])
},
methods: {
// 這裏的mapActions對應的是store.js裏面的actions,參數是個數組,裏面的元素其實就是store.js裏面的actions裏面的方法
...mapActions([
'setUserInfoAsync'
]),
getInfo(){
// 調用的方法是mapActions裏面的setUserInfoAsync
this.setUserInfoAsync()
},
},
mounted() {
}
}
</script>
<style scoped>
</style>
複製代碼
這裏咱們使用了Vuex的modules,以及namespaced屬性,modules容許咱們以modules的形式導出多個store,namespaced:true的話表明 咱們訪問store裏面的方法時要在對應的命名空間下
下面咱們改寫代碼,新建store文件夾,在下面新建index.js和modules文件夾,在modules文件夾下面新建一個咱們本身須要的文件夾wfq, 而後在wfq下面新建modules文件夾和index.js,而後在main.js裏修改store的路徑,目錄結構以下圖
代碼以下:
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import wfq from './modules/wfq'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
wfq
}
})
複製代碼
store/modules/wfq/index.js
// 找出以.js開頭的文件
const files = require.context('./modules', false, /\.js$/)
const modules = {}
files.keys().forEach(key => {
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})
export default {
namespaced: true,
modules
}
複製代碼
store/modules/wfq/modules/user.js
export default {
namespaced: true,
state: {
userInfo: {name:'WFQ'}
},
getters:{
getUserInfo(state){
return state.userInfo
}
},
mutations:{
setUserInfo(state,info){
state.userInfo = info
}
},
actions: {
setUserInfoAsync({commit}){
setTimeout(()=>{
let info = {
name: 'wfq',
age: 26
}
commit('setUserInfo',info)
},2000)
}
}
}
複製代碼
接下來看咱們怎麼使用:
<template>
<div>
<div>name:{{userInfo.name}}</div>
<el-button type="primary" size="small" @click="setInfo">設置用戶信息</el-button>
</div>
</template>
<script>
import {mapState,mapActions} from 'vuex'
export default {
name: "demo1",
data() {
return {}
},
computed:{
...mapState('wfq/user',[
'userInfo',
]),
},
methods: {
...mapActions('wfq/user',[
'setUserInfoAsync',
]),
setInfo(){
this.setUserInfoAsync();
},
},
mounted() {
}
}
</script>
複製代碼
使用modules修改後,mapState和mapActions要在第一個參數加上路徑,'wfq/user',這也就證實了namespaced的做用
接下來再思考一個問題,若是我在一個store文件(例如user.js)裏面想調用另外一個store的方法怎麼辦,好比,在獲得用戶的信息後, 我想直接調用該用戶的訂單信息,而後存儲在vuex中怎麼辦?咱們知道,獲取訂單信息是一個異步操做,咱們要放在actions裏面,而actions裏面的 方法怎麼觸發呢?使用dispatch 咱們新建一個store文件,order.js,此時目錄結構以下圖
代碼以下:
export default {
namespaced: true,
state: {
orderList:[]
},
getters:{
},
mutations:{
},
actions: {
setOrderListByUser({state},userInfo){
if(userInfo.name === 'wfq'){
let orderlist = ['order1','order2']
state.orderList = orderlist
}
}
}
}
複製代碼
下面咱們修改user.js的代碼以下:
actions: {
setUserInfoAsync({commit,dispatch}){
setTimeout(()=>{
let info = {
name: 'wfq',
age: 26
}
commit('setUserInfo',info)
dispatch('wfq/order/setOrderListByUser',info,{ root: true })
},2000)
}
}
複製代碼
咱們使用dispatch來觸發order下面的setOrderListByUser的方法,並傳入用戶信息,注意:這裏要設置{ root: true }, 這樣咱們就能在別的頁面獲取到order.js裏面的state下面的orderList的數據了,注意:別忘了去main.js裏面修改store的路徑