Vue3 之 Vuex - 状态管理

目录

一、概念

1. 状态管理

2. Vuex的状态管理

3. 单一状态树 

二、Vuex 的基本使用 

1. Vuex的安装

2. 创建store

3. 在store文件夹下创建index.js

4. 在main.js中引入 

5. 组件中使用sotre

6. 效果 

三、核心概念 State

1. 直接使用

2. mapState

使用 

封装 useState.js 文件

        代码

        使用

四、核心概念 Getters

1. 基本使用

代码

使用

2. getters第二个参数

代码

使用

3. getters的返回函数

代码

使用

4. mapGetters

使用

封装 useGetters.js 文件 

        代码

        使用

五、核心概念 Mutations

1. 重要原则 

2. 基本使用

代码

使用

3. 携带数据

代码

使用

4. 常量类型

定义mutation_types.js

代码

使用

5. mapMutations

使用

封装 useMutations.js 文件

        代码

        使用 

六、核心概念 Actions

1. 基本使用

代码

使用

2. 传递参数

代码

使用

3. mapActions

使用

封装 useActions.js 方法

        代码

        使用

4. 异步操作

代码

使用

七、核心概念 Module

1. 局部状态

01 - 定义模块A.js

02 - 定义store.js

03 - 使用

2. 命名空间

01 - 基本使用

        定义模块A.js

        使用

02 - module修改或派发根组件


一、概念

vue2 契合 vuex      |      vue3 契合 pinia

1. 状态管理

在开发中,应用程序需要处理各种各样的数据,这些数据需要保存在应用程序中的某一个位置,对于这些数据的管理就称之为是状态管理

  • 在Vue开发中,使用组件化的开发方式
  • 而在组件中定义data或者在setup中返回使用的数据,这些数
    据称之为state
  • 在模块template中可以使用这些数据,模块最终会被渲染成
    DOM,称之为View
  • 在模块中会产生一些行为事件,处理这些行为事件时,有可能
    会修改state,这些行为事件称之为actions 

2. Vuex的状态管理

  • 可以考虑将组件的内部状态抽离出来,以一个全局单例的方式来管理
  • 在这种模式下,组件树构成了一个巨大的 “试图View”
  • 不管在树的哪个位置,任何组件都能获取状态或者触发行为
  • 通过定义和隔离状态管理中的各个概念,并通过强制性的规则来维护视图和状态间的独立性,代码会变得更加结构化和易于维护、跟踪

3. 单一状态树 

Vuex 使用单一状态树 : 

  • 一个对象就包含了全部的应用层级的状态
  • 采用的是SSOT,Single Source of Truth,也可以翻译成单一数据源
  • 每个应用将仅仅包含一个 store 实例
    • 单状态树和模块化并不冲突,可以使用module模块

单一状态树的优势 : 

  • 如果状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难
  • 所以Vuex使用了单一状态树来管理应用层级的全部状态
  • 单一状态树能够让我们最直接的方式找到某个状态的片段
  • 而且在之后的维护和调试过程中,也可以非常方便的管理和维护

单一状态树的缺点 : 不够灵活

二、Vuex 的基本使用 

1. Vuex的安装

npm install vuex

2. 创建store

每一个Vuex应用的核心就是store(仓库)

store本质上是一个容器,它包含着你的应用中大部分的状态(state)

Vuex和单纯的全局对象的区别 : 

  • 第一:Vuex的状态存储是响应式的
    • 当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会被更新
  • 第二:不能直接改变store中的状态
    • 改变store中的状态的唯一途径就显示提交 (commit) mutation
    • 这样使得我们可以方便的跟踪每一个状态的变化,从而让我们能够通过一些工具帮助我们更好的管理应用的状态

3. 在store文件夹下创建index.js

// 1. 引入
import { createStore } from 'vuex';

// 2. 创建store对象
const store = createStore({
  // 3. 定义state
  state: () => ({
    // 4. 定义数据
    count: 100
  }),
  // 5. 定义mutations
  mutations: {
    // 6. 定义方法
    increment(state) {
      state.count++;
    }
  }
});

// 5. 导出
export default store;

4. 在main.js中引入 

import { createApp } from 'vue';
import App from './App.vue';
// 1. 导入
import store from './store';
// 2. 使用
createApp(App).use(store).mount('#app');

5. 组件中使用sotre

<template>
  <div class="app">App 页面</div>
  <!-- 1. 模版中使用 -->
  <h2>模版 : {{ $store.state.count }}</h2>
  <h2>computed : {{ storeCount }}</h2>
  <h2>解构count : {{ count }}</h2>

  <button @click="btnClick">增加</button>
</template>

<script setup>
// 2. 在js中使用
import { useStore } from 'vuex';
import { computed, toRefs } from 'vue';

const store = useStore();
console.log(store.state.count);

// 01 - computed包裹一下变成响应式
const storeCount = computed(() => store.state.count);
// 02 - 解构成ref对象
const { count } = toRefs(store.state);

// 监听按钮的点击
const btnClick = () => {
  // 触发mutation,让count++
  store.commit('increment');
};
</script>

6. 效果 

三、核心概念 State

1. 直接使用

<template>
  <div class="app">App 页面</div>
  <!-- 1. 模版中使用 -->
  <h2>模版 : {{ $store.state.count }}</h2>
  <h2>computed : {{ storeCount }}</h2>
  <h2>解构count : {{ count }}</h2>
</template>

<script setup>
// 2. 在js中使用
import { useStore } from 'vuex';
import { computed, toRefs } from 'vue';

const store = useStore();
console.log(store.state.count);

// 01 - computed包裹一下变成响应式
const storeCount = computed(() => store.state.count);
// 02 - 解构成ref对象
const { count } = toRefs(store.state);
</script>

2. mapState

使用 

<template>
  <div class="app">App 页面</div>
  <h2>模版 : {{ $store.state.count }}</h2>
  <h2>mapState : {{ cCount }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore, mapState } from 'vuex';
import { computed } from 'vue';

// 1. 拿到store对象
const store = useStore();
// 2. 使用mapState解构出方法
// const { count } = mapState(['count']);
// 数组和对象都可以
const { count } = mapState({
  count: (state) => state.count
});
// 3. 拿到对应的值
/**
 * count => 底层还是通过this.$store.state.count去拿的
 * setup 中没有this,所以传递过去时需要显示绑定一个$store
 * 
 * 通过显示绑定bind对象,让this指向这个对象
 * 然后底层就能拿到this.$store了
 */
const cCount = computed(count.bind({ $store: store }));

const btnClick = () => {
  store.commit('increment');
};
</script>

封装 useState.js 文件

        代码

import { useStore, mapState } from 'vuex';
import { computed } from 'vue';

export default function useState(mapper) {
  // 1. 拿到store对象
  const store = useStore();
  // 2. 使用mapState拿到对应的方法
  const stateFnsObj = mapState(mapper);
  // 4. 定一个接受对象
  const newState = {};
  // 5.遍历
  Object.keys(stateFnsObj).forEach((key) => {
    // 6. 生成绑定过的对象
    newState[key] = computed(stateFnsObj[key].bind({ $store: store }));
  });
  // 7. 返回
  return newState;
}

        使用

<template>
  <div class="app">App 页面</div>
  <h2>模版 : {{ $store.state.count }}</h2>
  <!-- 3. 展示 -->
  <h2>封装哒 : {{ fCount }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore } from 'vuex';
// 1. 导入封装的方法
import useState from './hooks/useState';
// 2. 使用
const { count: fCount } = useState(['count']);

const store = useStore();
const btnClick = () => {
  store.commit('increment');
};
</script>

四、核心概念 Getters

1. 基本使用

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  // 定义getters
  getters: {
    doubleCount(state) {
      return state.count * 2;
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>
  <h2>模版 : {{ $store.state.count }}</h2>
  <!-- 使用getters -->
  <h2>doubleCount : {{ $store.getters.doubleCount }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore } from 'vuex';

const store = useStore();
const btnClick = () => {
  store.commit('increment');
};
</script>

2. getters第二个参数

getters可以接收第二个参数,用来调用其他的getters

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  getters: {
    doubleCount(state, getters) {
      // 可以调用其他的getters函数
      return state.count * 2 + getters.mathRanDom;
    },
    // 生成[5,50)的随机数
    mathRanDom() {
      return Math.floor(Math.random() * 45) + 5;
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>
  <h2>模版 : {{ $store.state.count }}</h2>
  <h2>random : {{ $store.getters.mathRanDom }}</h2>

  <!-- 使用getters -->
  <h2>doubleCount : {{ $store.getters.doubleCount }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore } from 'vuex';

const store = useStore();
const btnClick = () => {
  store.commit('increment');
};
</script>

3. getters的返回函数

getters中的函数本身,可以返回一个函数,可用来接受参数

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  getters: {
    doubleCount(state, getters) {
      // 可以调用其他的getters函数
      return state.count * 2 + getters.mathRanDom;
    },
    // 生成[5,50)的随机数
    mathRanDom() {
      return Math.floor(Math.random() * 45) + 5;
    },
    countAddNum(state) {
      // 可用来接受传进来的参数
      return function (num) {
        return state.count + num;
      };
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>
  <h2>模版 : {{ $store.state.count }}</h2>

  <!-- 基本使用getters -->
  <h2>doubleCount : {{ $store.getters.doubleCount }}</h2>

  <!-- 随机数 -->
  <h2>random : {{ $store.getters.mathRanDom }}</h2>

  <!-- 传递参数 -->
  <h3>countAddNum : {{ $store.getters.countAddNum(10) }}</h3>
  <h3>countAddNum : {{ $store.getters.countAddNum(20) }}</h3>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore } from 'vuex';

const store = useStore();
const btnClick = () => {
  store.commit('increment');
};
</script>

4. mapGetters

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ doubleCount }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { computed, toRefs, watch, watchEffect } from 'vue';
import { useStore, mapGetters } from 'vuex';

const store = useStore();
// 1. 第一种方法
// const { doubleCount } = toRefs(store.getters);
// 2. 第二种方法
// const doubleCount = computed(() => store.getters.doubleCount);

// 3. 第三种方法,使用mapGetters
const { doubleCount: doubleCountFn } = mapGetters(['doubleCount']);
const doubleCount = computed(doubleCountFn.bind({ $store: store }));

// 这样时时打印数据
watchEffect(() => {
  console.log(doubleCount.value);
});

const btnClick = () => {
  store.commit('increment');
};
</script>

封装 useGetters.js 文件 

        代码

import { useStore, mapGetters } from 'vuex';
import { computed } from 'vue';

export default function useGetters(mapper) {
  const store = useStore();
  // 1. 接受全部getters
  const gettersFn = mapGetters(mapper);
  // 2. 定义新的函数数组
  const newGetters = {};
  // 3. 遍历绑定
  Object.keys(gettersFn).forEach((key) => {
    newGetters[key] = computed(gettersFn[key].bind({ $store: store }));
  });
  // 返沪
  return newGetters;
}

        使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ doubleCount }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { watchEffect } from 'vue';
import { useStore } from 'vuex';
// 1. 导入
import useGetters from '@/hooks/useGetters';

// 2. 使用
const { doubleCount } = useGetters(['doubleCount']);

const store = useStore();
const btnClick = () => {
  store.commit('increment');
};
// 这样时时打印数据
watchEffect(() => {
  console.log(doubleCount.value);
});
</script>

五、核心概念 Mutations

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

1. 重要原则 

 mutation 必须是同步函数

  • 因为devtool工具会记录mutation的日记
  • 每一条mutation被记录,devtools都需要捕捉到前一状态和后一状态的快照
  • 但是在mutation中执行异步操作,就无法追踪到数据的变化 

2. 基本使用

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    increment(state) {
      state.count++;
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore } from 'vuex';

const store = useStore();
const btnClick = () => {
  // 使用mutation中定义的方法
  store.commit('increment');
};
</script>

3. 携带数据

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    // 接受传递过来的参数
    increment(state, num) {
      state.count += num;
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore } from 'vuex';

const store = useStore();
const btnClick = () => {
  // 传递数据
  store.commit('increment', 10);
};
</script>

4. 常量类型

定义mutation_types.js

// 定义成常量类型
export const INCREMENT = 'increment';

代码

import { createStore } from 'vuex';
// 1. 导入
import { INCREMENT } from './mutation_types';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    // 2. 使用常量作为名称,使用计算属性值
    [INCREMENT](state, num) {
      state.count += num;
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore } from 'vuex';
// 1. 导入
import { INCREMENT } from '@/store/mutation_types';

const store = useStore();
const btnClick = () => {
  // 2. 使用
  store.commit(INCREMENT, 10);
};
</script>

5. mapMutations

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { useStore, mapMutations } from 'vuex';
import { INCREMENT } from '@/store/mutation_types';

const store = useStore();

// 1. 接受全部函数
const mutationFns = mapMutations([INCREMENT]);
// 2. 定义新的函数数组
const newMutations = {};
// 3. 遍历绑定
Object.keys(mutationFns).forEach((key) => {
  newMutations[key] = mutationFns[key].bind({ $store: store });
});
// 4. 从新生成的函数数组中解构出来
const { increment } = newMutations;
const btnClick = () => {
  // 5. 使用
  increment(10);
};
</script>

封装 useMutations.js 文件

        代码

import { useStore, mapMutations } from 'vuex';

export default function useMutations(mapper) {
  const store = useStore();
  // 1. 接受全部函数
  const mutationFns = mapMutations(mapper);
  // 2. 定义新的函数数组
  const newMutations = {};
  // 3. 遍历绑定
  Object.keys(mutationFns).forEach((key) => {
    newMutations[key] = mutationFns[key].bind({ $store: store });
  });
  // 返回对象
  return newMutations;
}

        使用 

<script setup>
import { useStore, mapMutations } from 'vuex';
// 1. 导入
import useMutations from '@/hooks/useMutations';
// 2. 解构
const { increment } = useMutations(['increment']);
const btnClick = () => {
  // 3. 使用
  increment(10);
};
</script>

六、核心概念 Actions

Action类似于mutation

  • Action提交的是mutation,而不是直接变更状态
  • Action可以包含任意异步操作

参数context : 

  • context是一个和store实例均有相同方法和属性的context对象
  • 所以可以从其中获取到commit方法来提交一个mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters
  • context不是store对象

1. 基本使用

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  getters: {
    doubleCount(state, getters) {
      return state.count * 2 + getters.mathRanDom;
    },
    mathRanDom() {
      return Math.floor(Math.random() * 45) + 5;
    }
  },
  actions: {
    // 定义actions方法
    incrementAction(context) {
      // 1. 可进行接口请求
      // balabalabala~
      // 2. 通过mutation来修改state的状态
      context.commit('increment');
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { watchEffect } from 'vue';
import { useStore } from 'vuex';

const store = useStore();

const btnClick = () => {
  // 调用action方法
  store.dispatch('incrementAction');
};
</script>

2. 传递参数

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    increment(state, num = 10) {
      state.count += num;
    }
  },
  getters: {
    doubleCount(state, getters) {
      return state.count * 2 + getters.mathRanDom;
    },
    mathRanDom() {
      return Math.floor(Math.random() * 45) + 5;
    }
  },
  actions: {
    // 定义actions方法,接受参数
    incrementAction(context, num) {
      // 调用mutations方法
      context.commit('increment', num);
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { watchEffect } from 'vue';
import { useStore } from 'vuex';

const store = useStore();

const btnClick = () => {
  // 调用action方法,传递参数
  store.dispatch('incrementAction', 9);
};
</script>

3. mapActions

使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { watchEffect } from 'vue';
import { useStore, mapActions } from 'vuex';

const store = useStore();
// 1. 接受全部的actions
const actionsFn = mapActions(['incrementAction']);
// 2. 定义新的actions对象
const newActions = {};
// 3. 遍历
Object.keys(actionsFn).forEach((key) => {
  newActions[key] = actionsFn[key].bind({ $store: store });
});
// 4. 解构
const { incrementAction } = newActions;
const btnClick = () => {
  // 5. 使用
  incrementAction(9);
};
</script>

封装 useActions.js 方法

        代码

import { useStore, mapActions } from 'vuex';

export default function useActions(mapper) {
  const store = useStore();
  // 1. 接受全部的actions
  const actionsFn = mapActions(['incrementAction']);
  // 2. 定义新的actions对象
  const newActions = {};
  // 3. 遍历
  Object.keys(actionsFn).forEach((key) => {
    newActions[key] = actionsFn[key].bind({ $store: store });
  });
  return newActions;
}

        使用

<template>
  <div class="app">App 页面</div>

  <h2>{{ $store.state.count }}</h2>

  <button @click="btnClick">改变</button>
</template>

<script setup>
import { watchEffect } from 'vue';
import { useStore, mapActions } from 'vuex';
// 1. 导入
import useActions from '@/hooks/useActions';
// 2. 解构
const { incrementAction } = useActions(['incrementAction']);
const btnClick = () => {
  // 5. 使用
  incrementAction(9);
};
</script>

4. 异步操作

代码

import { createStore } from 'vuex';

const store = createStore({
  state: () => ({
    // 1. 保存请求来的数据
    arrayList: []
  }),
  mutations: {
    // 2. 保存数据到 arrayList 中
    saveArrayList(state, list) {
      state.arrayList = list;
    }
  },
  actions: {
    // 3. 定义异步请求actions
    async fetchDataList(context) {
      /**
       * 1. 请求
       */
      // fetch('http://xxxx').then((res) => {
      //   res.json().then((data) => {
      //     console.log(data);
      //     context.commit('saveArrayList', data.list);
      //   });
      // });

      /**
       * 2. 优化,Promise链式调用
       */
      // fetch('http://xxxx')
      //   .then((res) => {
      //     return res.json();
      //   })
      //   .then((data) => {
      //     console.log(data);
      //     context.commit('saveArrayList', data.list);
      //   });

      /**
       * 3. 使用async await
       */
      // const res = await fetch('http://xxxx');
      // const data = await res.json();
      // context.commit('saveArrayList', data.list);

      /**
       * 4. 模拟,并返回一个promise
       */
      return new Promise((resolve) => {
        setTimeout(() => {
          const data = [1, 2, 3, 4, 5];
          // 保存在state中
          context.commit('saveArrayList', data);
          // 把数据返回出去
          resolve(data);
        }, 1000);
      });
    }
  }
});

export default store;

使用

<template>
  <div class="app">App 页面</div>
  <!-- 3. 显示 -->
  <h2>{{ dataList }}</h2>
  <!-- 4. 也可以直接显示 -->
  <h2>{{ $store.state.arrayList }}</h2>

  <h2></h2>
</template>

<script setup>
import { ref } from 'vue';
import { useStore } from 'vuex';

const store = useStore();
const dataList = ref([]);
// 1. 调用dispatch方法,请求数据
store.dispatch('fetchDataList').then((res) => {
  // 2. 拿到数据
  dataList.value = res;
  console.log(res);
});
</script>

七、核心概念 Module

Module : 

  • 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变得非常复杂时,store 对象就有可能变得相当臃肿
  • 为了解决以上问题,Vuex 可以将 store 分割成模块(module)
  • 每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

1. 局部状态

state : 使用的时候需要在前面加上模块的名称

mutation、getters、action : 默认集成在顶层中,可直接使用

 

ps : 所以,state可以定义相同的名字,但是其他的重名会报错,命名冲突问题

01 - 定义模块A.js

export default {
  // 模块数据
  state: () => ({
    m_Age: 18
  }),
  // 模块方法
  mutations: {
    // state => 指的是本模块的数据
    m_AddAge(state) {
      state.m_Age++;
    }
  },
  // 模块action
  actions: {
    /**
     * state => 指的是本模块的数据
     * commit => 可调用所有方法
     * rootState => 指的是根模块的数据
     */
    m_AddAgeAction({ state, commit, rootState }) {
      // 调用本模块方法
      commit('m_AddAge');
      // 调用根模块方法
      commit('increment');
    }
  },
  // 模块action
  getters: {
    /**
     * state => 指的是本模块的数据
     * getters => 可调用所有getters
     * rootState => 指的是根模块的数据
     */
    getMAge(state, getters, rootState) {
      return state.m_Age;
    }
  }
};

02 - 定义store.js

import { createStore } from 'vuex';
// 1.导入模块
import moduleA from './moduleA';

const store = createStore({
  state: () => ({
    count: 100
  }),
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAction({ commit }) {
      commit('increment');
    }
  },
  getters: {
    getCount(state) {
      return state.count;
    }
  },
  // 2. 注册一下
  modules: {
    moduleA
  }
});

export default store;

03 - 使用

<template>
  <div class="app">App 页面</div>
  <h2>根目录 :</h2>
  count : {{ $store.state.count }}<br />
  count : {{ $store.getters.getCount }}
  <hr />
  <hr />
  <hr />
  <h2>模块目录 :</h2>
  m_Age : {{ $store.state.moduleA.m_Age }} <br />
  m_Age : {{ $store.getters.getMAge }}
</template>

<script setup>
import { ref, computed } from 'vue';
import { useStore } from 'vuex';

const store = useStore();
/**
 * 调用根模块
 */
// state
const count = computed(() => store.state.count);
console.log('count', count.value);
// getters
const getCount = computed(() => store.getters.getCount);
console.log('getMAge', getCount.value);
// mutation
store.commit('increment');
// action
store.dispatch('incrementAction');

/**
 * 调用模块内
 */
// state
const m_Age = computed(() => store.state.moduleA.m_Age);
console.log('m_Age', m_Age.value);
// getters
const getMAge = computed(() => store.getters.getMAge);
console.log('getMAge', getMAge.value);
// mutation
store.commit('m_AddAge');
// action
store.dispatch('m_AddAgeAction');
</script>

2. 命名空间

默认情况下,模块内部的action、mutation、getters仍然是注册在全局的命名空间中的 : 

  • 这样使得多个模块能够对同一个 action 或 mutation 作出响应
  • Getter 同样也默认注册在全局命名空间

如果希望模块具有更高的封装度和复用性

  • 可以添加 namespaced: true 的方式使其成为带命名空间的模块
  • 当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名

01 - 基本使用

        定义模块A.js

export default {
  // 加上这个属性
  namespaced: true,
  state: () => ({
    m_Age: 18
  }),
  ......
};

        使用

<template>
  <div class="app">App 页面</div>
  <h2>根目录 :</h2>
  count : {{ $store.state.count }}<br />
  count : {{ $store.getters.getCount }}
  <hr />
  <hr />
  <hr />
  <h2>模块目录 :</h2>
  m_Age : {{ $store.state.moduleA.m_Age }} <br />
  m_Age : {{ $store.getters['moduleA/getMAge'] }}
</template>

<script setup>
import { ref, computed } from 'vue';
import { useStore } from 'vuex';

const store = useStore();
/**
 * 调用根模块
 */
// state
const count = computed(() => store.state.count);
console.log('count', count.value);
// getters
const getCount = computed(() => store.getters.getCount);
console.log('getMAge', getCount.value);
// mutation
store.commit('increment');
// action
store.dispatch('incrementAction');

/**
 * 调用模块内
 */
// state
const m_Age = computed(() => store.state.moduleA.m_Age);
console.log('m_Age', m_Age.value);
// getters
const getMAge = computed(() => store.getters['moduleA/getMAge']);
console.log('getMAge', getMAge.value);
// mutation
store.commit('moduleA/m_AddAge');
// action
store.dispatch('moduleA/m_AddAgeAction');
</script>

02 - module修改或派发根组件

如果希望在action中修改root中的state

 

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值