Vue Vuex 学习

118 阅读1分钟

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

// vuex 动态注册一个 modules
store.registerModule('c', {
  state: {
    text: 3
  }
})

// vuex 动态解绑一个 modules
// store.unregisterModule('c')

// vuex 监听一个指定字段是否发生变化
// store.watch((state) => state.count + 1, (newCount) => {
// store.watch((state) => state.count, (newCount) => {
//   console.log('new count watch', newCount) 
// })

// // vuex 拿到所有 mutation 的变化
// store.subscribe((mutation, state) => {
//   // 触动了 mutation 里面的哪个方法
//   console.log(mutation.type)
//   // mutation 里面更新的最新值
//   console.log(mutation.payload)
// })

// vuex 拿到所有 action 的变化
// store.subscribeAction((action, state) => {
//   // 触动了 action 里面的哪个方法
//   console.log(action.type)
//   // action 里面更新的最新值
//   console.log(action.payload)
// })

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

store - index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 是否为开发环境
const isDev = process.env.NODE_ENV === 'development'

// 建立一个 Store
const store = new Vuex.Store({
  // 开启规范检测
  strict: isDev,
  // 定义属性
  state: {
    count: 0,
    firstName: 'dzm',
    lastName: 'xyq'
  },
  // 更新(同步),mutations 不能存在异步操作
  mutations: {
    updateCount (state, num) {
      state.count = num
    }
  },
  // 更新(异步),actions 允许异步操作
  actions: {
    updateCountAsync (store, data) {
      setTimeout(() => {
        store.commit('updateCount', data.num)
      }, data.time)
    }
  },
  // 获取计算属性
  getters: {
    fullName (state) {
      return `${state.firstName} ${state.lastName}`
    }
  },
  // 插件列表
  plugins: [
    (store) => {
      console.log('初始化插件列表')
    }
  ],
  // 模块功能
  modules: {
    // 模块A
    a: {
      // 默认 vuex 是会把所有的 mutations 放在一个全局的对象中,如果需要根据模块区分,那么需要在模块中配置 namespaced: true
      // 这样的好处就是,每个模块里面都可以写相同名字的 mutations,如果不声明,那么所有的 mutations 都会在一个对象中,就会命名重复冲突
      namespaced: true,
      state: {
        text: 1
      },
      mutations: {
        updateText (state, text) {
          // 这里面的 state 就是 a 模块里面的 state 了
          state.text = text
        }
      },
      getters: {
        // state 当前A模块的 state
        // getters 当前A模块所有的 getters
        // rootState 当前父类的 state
        textPlus (state, getters, rootState) {
          // 这样就可以直接使用父类中的属性了
          return state.text + rootState.count
          // 同时也可以使用别的模块中的值
          // return state.text + rootState.b.text
        }
      },
      actions: {
        // add (ctx) { }
        add ({ state, commit, rootState }) { 
          // 直接调用A模块内的 updateText
          // commit('updateText', rootState.count)
          // 直接调用父模块内的 updateCount
          commit('updateCount', 123, { root: true })
        }
      },
      modules: {
        // 还可以在子模块中继续嵌套模块
      }
    },
    // 模块B
    b: {
      state: {
        text: 2
      }
    }
  }
})

export default store

App.vue

<template>
  <div id="app">
    <!-- 显示vuex的值 -->
    <div>{{count}}</div>
    <div>{{fullName}}</div>
    <div>{{textA}}</div>
    <div>{{textPlus}}</div>
    <div>{{textC}}</div>
  </div>
</template>

<script>
import { 
  mapState,
  mapGetters,
  mapActions,
  mapMutations
} from 'vuex'
export default {
  name: 'app',
  mounted () {
    // vuex 不能直接通过点语法直接修改数据,这么写会报错的: 
    // this.$store.state.count = 3

    // 下面这个是 mutations 同步修改:
    // let i = 1
    // setInterval(() => {
    //   this.$store.commit('updateCount', i++)
    // }, 1000)

    // mutations 同步修改使用 ...mapMutations 之后可以这么使用:
    let i = 1
    setInterval(() => {
      this.updateCount(i++)
    }, 1000)

    // 下面这个是 actions 异步修改:
    // this.$store.dispatch('updateCountAsync', {
    //   num: 5,
    //   time: 1000
    // })

    // actions 异步修改使用 ...mapActions 之后可以这么使用:
    // this.updateCountAsync({
    //   num: 5,
    //   time: 1000
    // })

    // modules 根据模块获取数据
    // 通过 ...mapMutations 修改数据
    // namespaced: false
    // this.updateText('123')
    // namespaced: true
    // this['a/updateText']('456')
    this['a/add']()

  },
  methods: {
    ...mapActions(['updateCountAsync', 'a/add']),
    // updateText 是模块里面的更新属性,但是默认 vuex 是会把所有的 mutations 放在一个全局的对象中,如果需要根据模块区分,那么需要在模块中配置:
    // namespaced: true, 这样的好处就是,每个模块里面都可以写相同名字的 mutations, 如果不声明,那么所有的 mutations 都会在一个对象中,就会命名重复冲突

    // namespaced: false
    // ...mapMutations(['updateCount', 'updateText'])
    // namespaced: true
    ...mapMutations(['updateCount', 'a/updateText'])
  },
  computed: {

    // mapState
    // 获取属性方式一
    ...mapState(['count']),
    // 获取属性方式二
    // ...mapState({
    //   counter: 'count'
    // }),
    // 获取属性方式三
    // ...mapState({
    //   count: (state) => state.count
    // }),
    // 获取属性方式四
    // count () {
    //   return this.$store.state.count
    // },

    // mapGetters 也跟上面一样
    // 如果 namespaced: true, 那么 'a/textPlus' 这种方式是不好去使用的
    // ...mapGetters(['fullName', 'a/textPlus']),
    // 就需要这样去使用
    ...mapGetters({
      fullName: 'fullName', 
      textPlus: 'a/textPlus'
    }),
    // fullName () {
    //   return this.$store.getters.fullName
    // }

    // modules 根据模块获取数据
    // 获取属性方式一
    // textA () {
    //   return this.$store.state.a.text
    // },
    // 获取属性方式二
    ...mapState({
      textA: state => state.a.text,
      textC: state => state.c.text
    })
  }
}
</script>

<style scoped>
</style>