vuex的使用总结


1.定义一个store

// store.ts
import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
import moduleA from '@/store/module/moduleA';
import moduleB from '@/store/module/moduleB';

export interface State {
  count: number,
  name:string,
  arr:number[]
}

export const key: InjectionKey<Store<State>> = Symbol()

export const store = createStore<State>({
   state() {
    return {
      count: 0,
      name: 'lgp',
      arr: [1, 2, 3, 4, 5, 6],
    };
  },
  getters: {
    sortArr(state) {
      return state.arr.sort((a, b) => b - a);
    },
    getNum(state, getters) {
      const max = Math.max(...state.arr);
      const arr1 = getters.sortArr as number[];
      return arr1.map((item) => item * max);
    },
  },
  mutation:{
    add(state,payload){
       state.count+=payload
     }
   },
  actions:{
    addAction(ctx,payload){
       ctx.commit('add',payload);
     }
   },
  modules: {
    produce: moduleA,
    car: moduleB,
  },
})

// 定义自己的 `useStore` 组合式函数
export function useMyStore () {
  return baseUseStore(key)
}

2.安装store

// main.ts
import { createApp } from 'vue'
import { store, key } from './store'

const app = createApp({ ... })

// 传入 injection key
app.use(store, key)

app.mount('#app')

3.使用store

// vue 组件
import { useMyStore } from './store'
export default {
  setup () {
    const store = useMyStore(key)
    store.state.count // 类型为 number
  }
}

4核心概念

Strore

1.定义store

store可以是一个对象,或者是一个函数返回一个对象

export interface State {
 count: number,
 name:string,
 arr:number[]
}
export const store = createStore<State>({
  state() {
   return {
     count: 0,
     name: 'lgp',
     arr: [1, 2, 3, 4, 5, 6],
   };
 },

2.组件内获取store的state数据

//单个获取数据
const count =computed(()=>{
     return store.state.count
])

//批量获取数据mapstate
const storeState = mapState(['count', 'name']);
const result = {};
Object.keys(storeState).forEach((key) => {
  result[key] = computed(storeState[key].bind({ $store: store }));
});
const { count, name } = { ...result };
watchEffect(() => {
  console.log(count.value, name.value);
});

Getters

1.定义getters

Getter 接受 state 作为其第一个参数:
Getter 也可以接受其他 getter 作为第二个参数:
也可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查 询时非常有用。
注意区别:
getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的。
本质上getter的结果缓存其实是computed来实现的本身不具备缓存的效果

  getters: {
    sortArr(state) {
      return state.arr.sort((a, b) => b - a);
    },
    getNum:(state, getters)=>(maxNum:number)=> {
      const max =maxNum || Math.max(...state.arr);
      const arr1 = getters.sortArr as number[];
      return arr1.map((item) => item * max);
    },
  },

2.组件内使用getters

import { useMyStore } from '@/store';
const store = useMyStore();
const getNum = computed(() => store.getters.getNum(10));
console.log(`getNum${getNum.value}`);

Mutation

1.定义一个mutation
*更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
*接受 state 作为第一个参数:
*你可以向 store.commit 传入额外的参数,即 mutation 的载荷(payload)
*一条重要的原则就是要记住 mutation 必须是同步函数:原因为了让devtools 捕捉状态,方便调试

  mutation:{
  add(state,payload){
     state.count+=payload
   }
 },

2.组件中使用mutation

store.commit('add',1)

Action

1.定义action
*Action 提交的是 mutation,而不是直接变更状态。
*Action 可以包含任意异步操作。
*接受一个与 store 实例具有相同方法和属性的 context 对象

  actions:{
    addAction(ctx,payload){
      return new Promise((resolve, reject) => {
        setTimeout(()=>{
          ctx.commit('add',payload);
          resolve()
        },3000)
      })
     },
   async actionA ({ commit }) {
    commit('gotData', await getData())
    },
   async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
},

2使用action

store.dispatch('addAction',1).then(()=>{}).catch(()=>{})

Module

1定义

const moduleA = {
 namespaced: true,   //true表示开启命名空间
 state: () => ({
   count: 0
 }),
 mutations: {
   increment (state) {
     // 这里的 `state` 对象是模块的局部状态
     state.count++
   }
 },
 actions: {
   incrementIfOddOnRootSum ({ state, commit, rootState }) {
     if ((state.count + rootState.count) % 2 === 1) {
       commit('increment')
     }
   }
 },
 getters: {
   doubleCount (state) {
     return state.count * 2
   }
 }
}
const moduleA = {
 state: () => ({ ... }),
 mutations: { ... },
 actions: { ... },
 getters: { ... }
}

const moduleB = {
 state: () => ({ ... }),
 mutations: { ... },
 actions: { ... }
}

const store = createStore({
 modules: {
   a: moduleA,
   b: moduleB
 }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

**2命名空间 **
namespaced: true 开启命名空间
默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的——这样使得多个模块能够对同一个 action 或 mutation 作出响应。Getter 同样也默认注册在全局命名空间,但是目前这并非出于功能上的目的(仅仅是维持现状来避免非兼容性变更)。必须注意,不要在不同的、无命名空间的模块中定义两个相同的 getter 从而导致错误。

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

启用了命名空间的 getter 和 action 会收到局部化的 getter,dispatch 和 commit。换言之,你在使用模块内容(module assets)时不需要在同一模块内额外添加空间名前缀。更改 namespaced 属性后不需要修改模块内的代码。

如果你希望使用全局 state 和 getter,rootState 和 rootGetters 会作为第三和第四参数传入 getter,也会通过 context 对象的属性传入 action

若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。
例如:

 actions: {
      // 在这个模块中, dispatch 和 commit 也被局部化了
      // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
      someAction ({ dispatch, commit, getters, rootGetters }) {
        getters.someGetter // -> 'foo/someGetter'
        rootGetters.someGetter // -> 'someGetter'

        dispatch('someOtherAction') // -> 'foo/someOtherAction'
        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'

        commit('someMutation') // -> 'foo/someMutation'
        commit('someMutation', null, { root: true }) // -> 'someMutation'
      },
      someOtherAction (ctx, payload) { ... }
    }
    

3.组件内使用
可以通过打印出store的结构这样怎么获取store等就一目了然了

// store.dispatch(namespace + 'actionName')

//获取命名空间内的store
console.log(store.state.a.name);
console.log(store.state.b.name);

//提交命名空间内的mutation
store.commit('a/add',10)
//获取getters内容
const a=computed(()=>{
  return store.getters["a/getNum"]
})
//提交actions
store.dispatch('a/addAction','payload')

store.commit('b/add','payload')
const a=computed(()=>{
  return store.getters["b/getX"]
})
store.dispatch('b/addAction','payload')

命名空间内核心函数的参数
Getters
getters接受四个参数 state, getters, rootState, rootGetters

  getters: {
      // 在这个模块的 getter 中,`getters` 被局部化了
      // 你可以使用 getter 的第四个参数来调用 `rootGetters`
      someGetter (state, getters, rootState, rootGetters) {
        getters.someOtherGetter // -> 'foo/someOtherGetter'
        rootGetters.someOtherGetter // -> 'someOtherGetter'
      },

Actions
action 接受两个参数 ctx ,payload ctx包含{ dispatch, commit, getters, rootGetters }
若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。

 actions: {
      someOtherAction (ctx, payload) { ... },
      // 在这个模块中, dispatch 和 commit 也被局部化了
      // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
      someAction ({ dispatch, commit, getters, rootGetters }) {
        getters.someGetter // -> 'foo/someGetter'
        rootGetters.someGetter // -> 'someGetter'

        dispatch('someOtherAction') // -> 'foo/someOtherAction'
        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'

        commit('someMutation') // -> 'foo/someMutation'
        commit('someMutation', null, { root: true }) // -> 'someMutation'
      }
    }
  }

插件功能

Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数:

const myPlugin = (store) => {
 // 当 store 初始化后调用
 store.subscribe((mutation, state) => {
   // 每次 mutation 之后调用
   // mutation 的格式为 { type, payload }
 })
}

const store = createStore({
 // ...
 plugins: [myPlugin]
})

Vuex 自带一个日志插件用于一般的调试:

import createLogger from 'vuex/dist/logger'

const logger = createLogger({
  collapsed: false, // 自动展开记录的 mutation
  filter (mutation, stateBefore, stateAfter) {
    // 若 mutation 需要被记录,就让它返回 true 即可
    // 顺便,`mutation` 是个 { type, payload } 对象
    return mutation.type !== "aBlocklistedMutation"
  },
  actionFilter (action, state) {
    // 和 `filter` 一样,但是是针对 action 的
    // `action` 的格式是 `{ type, payload }`
    return action.type !== "aBlocklistedAction"
  },
  transformer (state) {
    // 在开始记录之前转换状态
    // 例如,只返回指定的子树
    return state.subTree
  },
  mutationTransformer (mutation) {
    // mutation 按照 { type, payload } 格式记录
    // 我们可以按任意方式格式化
    return mutation.type
  },
  actionTransformer (action) {
    // 和 `mutationTransformer` 一样,但是是针对 action 的
    return action.type
  },
  logActions: true, // 记录 action 日志
  logMutations: true, // 记录 mutation 日志
  logger: console, // 自定义 console 实现,默认为 `console`
})


const store = new Vuex.Store({
  plugins: [logger]
})

开启严格模式

*在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到
*严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。

const store = createStore({
  // ...
  strict: process.env.NODE_ENV !== 'production'
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值