Vuex學習筆記

一、Vuex之集成

1. 功能

處理前端路由的功能

2. 安裝

npm install vuex --save

3. 集成

在項目中新建兩個文件(store文件夾下)

index.js    // 路由配置
routes.js   // 路由內容

3.1 index.js

存放路由配置

  • 3.2.1 方式一:返回一個Vuex對象,全局import時皆為統一對象,不會自動釋放,所以在使用服務端渲染時會導致內存溢出
    import Vue from 'vue'
    import Vuex from 'vuex'
    // 使用Vuex
    Vue.use(Vuex)

    export default new Vuex.Store({
      state: {
        counts: 0
      },
      mutations: {
        updateCount (state, num) {
          state.count = num
        }
      }
    })
  • 3.2.2 方式二:返回一個方法,每次import創建一個新的Vuex
    import Vue from 'vue'
    import Vuex from 'vuex'
    // 使用Router
    Vue.use(Vuex)

    // 判斷是否處于開發環境
    const isDev = process.env.NODE_ENV === 'development'

    export default () => {
      return new Vuex.Store({
        // 開啟后不可以在外部直接修改state,只可在開發環境中使用
        strict: isDev
        state: {
          counts: 0
        },
        mutations: {
          updateCount (state, num) {
            state.count = num
          }
        }
      })
    }

3.2 main.js

    import createStore from './store/index.js'
    // 將store放入new Vue的配置項中

    const store = createStore()

    new Vue({
      store: store
    })

3.3 Component.vue (Vuex的使用)

通過this.$store使用

    // store對象
    this.$store
    // state
    this.$store.state.count
    // mutations
    this.$store.commit('updateCount', i)

二、Vuex之state和getters

1. 文件夾結構

+ store
  + state
    state.js
  + mutations
    mutations.js
  + getters
    getters.js
  index.js
    import Vue from 'vue'
    import Vuex from 'vuex'

    import defaultState from './state/state.js'
    import mutations from './mutations/mutation.js'
    import getters from './getters/getters.js'
    // 使用Router
    Vue.use(Vuex)

    export default () => {
      return new Vuex.Store({
        // 服務端渲染時會覆蓋state,所以此時使用defaultState
        state: defaultState,
        // 操作與數據無關
        mutations,
        getters
      })
    }

2. state

2.1 聲明

    export default {
      count: 0,
      firstName: 'Shi',
      lastName: 'Xinxin'
    }

2.2 使用

    this.$store.state.count

3. mutations

3.1 聲明

    export default {
      updateCount (state, num) {
        state.count = num
      }
    }

3.2 使用

    this.$store.commit('updateCount', i)

4. getters(類似組建中使用computed)

4.1 聲明

    export default {
      fullName (state) {
        return `${state.firstName} ${state.lastName}`
      }
    }

4.2 使用

    this.$store.getters.fullName

5. 幫助方法

Component.vue

import {
  mapState,
  mapGetters
} from 'vuex'

export default {
  computed: {
    ...mapState(['count']),
    // or
    ...mapState({
      counter: 'count'
    }),
    // or
    ...mapState({
      counter: (state) => state.count
    }),

    ... mapGetters(['fullName'])
  }
}

三、Vuex之mutation和action

1. 文件夾結構

+ store
  + state
    state.js
  + mutations
    mutations.js
  + getters
    getters.js
  + actions
    actions.js
  index.js
    import Vue from 'vue'
    import Vuex from 'vuex'

    import defaultState from './state/state.js'
    import mutations from './mutations/mutation.js'
    import getters from './getters/getters.js'
    import actions from './actions/actions.js'
    // 使用Router
    Vue.use(Vuex)

    export default () => {
      return new Vuex.Store({
        // 服務端渲染時會覆蓋state,所以此時使用defaultState
        state: defaultState,
        // 操作與數據無關
        mutations,
        getters,
        actions
      })
    }

2. mutation

專門修改state數據使用,但是可以直接在外部修改
必須是同步的操作,不可以有異步的代碼

2.1 聲明

只能有兩個參數,第一個參數為state,第二個參數為一個object

    export default {
      updateCount (state, data) {
        console.log(data.num1)
        console.log(data.num2)
      }
    }

2.2 使用

    this.$store.commit('updateCount', {
      num1: 1,
      num2: 2
    })

3. action

修改state,異步代碼

3.1 聲明

只能有兩個參數,第一個參數為state,第二個參數為一個object

    export default {
      updateCountAsync (state, data) {
        setTimeout(() => {
          store.commit('updateCount', data.num)
        }, data.time)
      }
    }

3.2 使用

    this.$store.dispach('updateCountAsync', {
      num: 5,
      time: 2000
    })

4. 幫助方法

Component.vue

import {
  mapState,
  mapGetters,
  mapActions,
  mapMutations
} from 'vuex'

export default {
  computed: {
    ...mapState(['count']),
    // or
    ...mapState({
      counter: 'count'
    }),
    // or
    ...mapState({
      counter: (state) => state.count
    }),

    ... mapGetters(['fullName'])
  },
  mounted () {
    this.updateCountAsync({
      num1: 1
      num2: 2000
    })
    this.updateCount({
      num1: 1,
      num1: 2
    })
  },
  methods: {
    ...mapActions(['updateCountAsync']),
    ...mapMutations(['updateCount'])
  }
}

四、Vuex之模塊

1. 文件夾結構

+ store
  + state
    state.js
  + mutations
    mutations.js
  + getters
    getters.js
  + actions
    actions.js
  index.js
    import Vue from 'vue'
    import Vuex from 'vuex'

    import defaultState from './state/state.js'
    import mutations from './mutations/mutation.js'
    import getters from './getters/getters.js'
    import actions from './actions/actions.js'
    // 使用Router
    Vue.use(Vuex)

    export default () => {
      return new Vuex.Store({
        // 服務端渲染時會覆蓋state,所以此時使用defaultState
        state: defaultState,
        // 操作與數據無關
        mutations,
        getters,
        actions,
        modules: {
          a: {
            state: {
              text: 1
            }
          },
          b: {
            state: {
              text: 2
            }
          }
        }
      })
    }

2. State

2.1 聲明

modules

index.js

    export default () => {
      return new Vuex.Store({
        modules: {
          a: {
            state: {
              text: 1
            }
          },
          b: {
            state: {
              text: 2
            }
          }
        }
      })
    }

2.2 使用

  • 方法一: this.$store.state.a.text

    Component.vue

    export default {
      computed: {
        textA () {
          return this.$store.state.a.text
        },
        textB () {
          return this.$store.state.b.text
        }
      }
    }
    
  • 方法二: mapState

    Component.vue

    export default {
      computed: {
        ...mapState({
          textA: state=>state.a.text
          textB: state=>state.b.text
        })
      }
    }
    

3. Mutation

3.1 聲明

modules

index.js

    export default () => {
      return new Vuex.Store({
        modules: {
          a: {
            // 未聲明方法放全局,聲明后為命名空間內
            namespaced: true,
            state: {
              text: 1
            },
            mutations: {
              updateText (state, text) {
                console.log('a.state', state)
                state.text = text
              }
            }
          },
          b: {
            state: {
              text: 2
            }
          }
        }
      })
    }

3.2 使用

mapMutations

Component.vue

    export default {
      mounted () {
        // 未聲明namespaced的話可以直接調用
        this.updateText('123')
        // 聲明了namespaced的話要用變量形式
        this['a/updateText']('123')
      },
      methods: {
        // 未聲明namespaced的話可以直接寫名字
        ...mapMutations(['updateText']),
        // 聲明了namespaced的話要加命名空間名稱
        ...mapMutations(['a/updateText'])
      }
    }

4. Getter

4.1 聲明

modules

index.js

    export default () => {
      return new Vuex.Store({
        modules: {
          a: {
            // 未聲明方法放全局,聲明后為命名空間內
            namespaced: true,
            state: {
              text: 1
            },
            mutations: {
              updateText (state, text) {
                console.log('a.state', state)
                state.text = text
              }
            },
            getters: {
              /**
                * state: 當前命名空間下的state
                * getters: 全局getters
                * rootState: 根目錄State,通過rootState可以得到全部state
                */
              textPlus (state, getters, rootState) {
                return state.text + rootState.b.text
              }
            }
          },
          b: {
            state: {
              text: 2
            }
          }
        }
      })
    }

4.2 使用

mapGetters

Component.vue

    export default {
      mounted () {
        console.log(this['a/textPlus'])
      },
      computed: {
        ...mapGetters(['a/textPlus'])
      }
    }

Component.vue

    export default {
      mounted () {
        console.log(this.textPlus)
      },
      computed: {
        ...mapGetters({
          textPlus: 'a/textPlus'
        })
      }
    }

5. Action

5.1 聲明

modules

index.js

    export default () => {
      return new Vuex.Store({
        modules: {
          a: {
            // 未聲明方法放全局,聲明后為命名空間內
            namespaced: true,
            state: {
              text: 1
            },
            mutations: {
              updateText (state, text) {
                console.log('a.state', state)
                state.text = text
              }
            },
            getters: {
              /**
                * state: 當前命名空間下的state
                * getters: 全局getters
                * rootState: 根目錄State,通過rootState可以得到全部state
                */
              textPlus (state, getters, rootState) {
                return state.text + rootState.b.text
              }
            },
            actions: {
              // add (ctx) {
              //   ctx.state
              //   ctx.commit
              //   ctx.rootState
              // }
              add ({state, commit, rootState})
                // updateText為本模塊mutation,加上{root: true}可在全局尋找
                commit (
                  'updateText',
                  rootState.count,
                  {root: true}
                )                
              }
            }
          },
          b: {
            state: {
              text: 2
            },
            actions: {
              testAction ({commit}) {
                commit(
                  'a/updateText',
                  'test'
                )
              }
            }
          }
        }
      })
    }

5.2 使用

mapActions

Component.vue

    export default {
      mounted () {
        this['a/add']()
      },
      methods: {
        // 未聲明namespaced的話可以直接寫名字,聲明了namespaced的話要加命名空間名稱
        ...mapActions(['a/add', 'testAction'])
      }
    }

注: 模塊可無限向下嵌套

6. 動態注冊模塊

6.1 聲明

main.js

store.registerModule('c', {
  state: {
    text: 3
  }
})

6.2 使用

Component.vue

    export default {
      computed: {
        textC: state => state.c.text
      }
    }

7. 熱更替(似乎存在問題,謹慎使用)

index.js

    export default () => {
      const store = new Vuex.Store({
        state: defaultState,
        mutations,
        getters,
        actions
      })
      if (module.hot) {
        module.hot.accept([
          './state/state',
          './mutations/mutations'
          './actions/actions',
          './getters/getters'
        ], () => {
          const newState = require('./state/state').default
          const newMutations = require('./mutations/mutations').default
          const newActions = require('./actions/actions').default
          const newGetters = require('./getters/getters').default

          store.hotUpdate({
            state: newState,
            mutations: newMutations,
            actions: newActions,
            getters: newGetters
          })
        })
      }
      return store
    }

五、Vuex之其他一些API和配置

1. 注銷模塊

main.js

    store.unregisterModule('c')

2. 監聽state

main.js

    store.watch(
      // 相當于getter
      (state) => {
        state.count + 1
      },
      // 值發生變化時觸發的回調函數
      (newCount) => {
        console.log('new count watched:', newCount)
      }
    )

3. 監聽mutation

main.js

    store.subscribe((mutation, state) => {
      console.log(mutation.type)
      console.log(mutation.payload);
    })

4. 監聽action

main.js

    store.subscribeAction((action, state) => {
      console.log(action.type)
      console.log(action.payload);
    })

5. 定制插件

index.js

    export default () => {
      const store = new Vuex.Store({
        // 可以有多個插件,放入一個數組之中
        plugins: [
          // 利用上面三條組合進行私人訂制
          (store) => {
            console.log('my plugin invoked')
          },
          ...
        ]
      })
      return store
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。