Vuex之模組

littlebirdflying發表於2018-09-13

module 中的 state

// store.js
export default () => {
  return new Vuex.Store({
    modules: {
      a: { // a 模組
        state: {
          text: 1
        }
      },
      b: { // b 模組
        state: {
          text: 2
        }
      }
    }
  })
}
複製程式碼
// app.vue
<template>
  <div id="app">
    <p>{{textA}} {{textB}}</p>
  </div>
</template>

<script>
import {
  mapState,
  mapGetters,
  mapActions,
  mapMutations
} from 'vuex'
export default {
  computed: {
    textA () {
      return this.$store.state.a.text // 通過模組的名稱空間
    },
    textB () {
      return this.$store.state.b.text
    } 
  }
}
</script>
複製程式碼

mapState 簡寫

computed: {
    // textA () {
    //   return this.$store.state.a.text
    // },
    ...mapState({
      textA: state => state.a.text
    })
  },
複製程式碼

module 中的 mutations

這裡沒有和 state 一樣通過模組來呼叫,vuex 預設會把所有的 mutation 放到全域性的名稱空間中。

// store 配置
modules: {
      a: {
        state: {
          text: 1
        },
        mutations: {
          updateText (state, text) { // 函式第一個引數是模組的 state 
            console.log('a.state', state)
            state.text = text
          }
        }
      },
      b: {
        state: {
          text: 2
        }
      }
    }
複製程式碼
// 元件內
  mounted () {
    this.updateText('123')
  },
  methods: {
    ...mapMutations(['updateCount', 'updateText']) // 傳入 mutations
  }
</script>
複製程式碼

namespaced

使 mutation 只在模組的名稱空間,可以通過設定 namespaced: true 來做,這樣在不同模組就可以使用相同命名的 mutaion 和 action 了。更加規範

// store 配置
modules: {
      a: {
        namespaced: true, // 模組的名稱空間
        state: {
          text: 1
        },
        mutations: {
          updateText (state, text) {
            console.log('a.state', state)
            state.text = text
          }
        }
      },
      b: {
        state: {
          text: 2
        }
      }
    }
複製程式碼
// 元件內
  mounted () {
    this.['a/updateText']('123') // 變數的形式
  },
  methods: {
    ...mapMutations(['updateCount', 'a/updateText']) // 傳入 mutations
  }
</script>
複製程式碼

module 中的 getters

下例,mapGetters 陣列的方式,在 template 裡用不太方便。

// store 配置
modules: {
      a: {
        namespaced: true,
        state: {
          text: 1
        },
        mutations: {
          updateText (state, text) {
            console.log('a.state', state)
            state.text = text
          }
        },
        getters: { // module 中的 getters
          textPlus (state) { // state 是此模組下的 state
            return state.text + 1
          }
        }
      },
      b: {
        state: {
          text: 2
        }
      }
    }
複製程式碼
// 元件內
mounted () {
    console.log(this.$store, this['a/textPlus']) // 列印出 textPlus
    let i = 1
    setInterval(() => {
      this.updateCount({
        num: i++,
        num2: 2
      })
    }, 1000)
    this.updateCountAsync({
      num: 5,
      time: 2000
    })
    this['a/updateText']('123')
  },
computed: {
    // textA () {
    //   return this.$store.state.a.text
    // },
    textB () {
      return this.$store.state.b.text
    },
    ...mapState({
      counter: (state) => state.count,
      textA: state => state.a.text
    }),
    ...mapGetters(['fullName', 'a/textPlus']) // mapGetters 陣列的方式
  },
複製程式碼

mapGetters 物件的方式

// 元件內
<template>
  <div id="app">
    <p>{{textPlus}}</p>
</template>
<script>
    computed: {
        ...mapGetters({ // mapGetters 接收物件的方式
          'fullName': 'fullName',
          textPlus: 'a/textPlus'
        })
      },
</script>
複製程式碼

接收全域性 state

模組下的 getters 可以接收到全域性的 state,通過全域性的 rootState,我們可以拿到其他模組的 state。

// store 配置
modules: {
      a: {
        namespaced: true,
        state: {
          text: 1
        },
        mutations: {
          updateText (state, text) {
            console.log('a.state', state)
            state.text = text
          }
        },
        getters: {
          textPlus (state, getters, rootState) { // state 是此模組下的 state
            return state.text + rootState.count + rootState.b.text // 拿到不同地方的 state
          }
        }
      },
      b: {
        state: {
          text: 2
        }
      }
    }
複製程式碼

module 中的 actions

// store 配置
modules: {
      a: {
        namespaced: true,
        state: {
          text: 1
        },
        mutations: {
          updateText (state, text) {
            console.log('a.state', state)
            state.text = text
          }
        },
        actions: {
          add ({ state, commit, rootState }) { // 從 ctx 中拿,ctx 和 store 類似
            commit('updateText', rootState.count) // 同一模組名稱空間下的
          }
        }
      }
}
複製程式碼
  mounted () {
    this['a/add']() // 執行
  },
  methods: {
    ...mapActions(['updateCountAsync', 'a/add']),  // 拿到方法
    ...mapMutations(['updateCount', 'a/updateText'])
  }
}
</script>
複製程式碼

呼叫全域性名稱空間的 mutations

使用 root: true

// store 配置
modules: {
      a: {
        namespaced: true,
        state: {
          text: 1
        },
        mutations: {
          updateText (state, text) {
            console.log('a.state', state)
            state.text = text
          }
        },
        getters: {
          textPlus (state, getters, rootState) { 
            return state.text + rootState.count + rootState.b.text
          }
        },
        actions: {
          add ({ state, commit, rootState }) { 
            commit('updateCount', { num: 56789 }, { root: true }) // 呼叫全域性 mutation updateCount
          }
        }
      },
複製程式碼
// 全域性 mutations
export default {
  updateCount (state, { num, num2 }) { 
    console.log(num2)
    state.count = num
  }
}
複製程式碼

動態註冊模組

// indexjs 應用主入口
store.registerModule('c', {
  state: {
    text: 3
  }
})
複製程式碼
// 元件內
// template
<p>{{textC}}</p>
// script
 computed: {
    ...mapState({
      textC: state => state.c.text
    })
  },
複製程式碼

相關文章