Vuex入门教程

一、vuex是什么

vue官方提供的状态管理器。用于处理全局的数据共享问题的。

二、vuex的仓库中的几个核心概念

  • state
    vuex中的数据源,专门存共享数据的地方。
  • getter
    可以针对现有的 state 数据或者其余的 getter 做的一个二次计算,可以理解为仓库的计算属性。
  • mutation
    唯一能够修改 state 数据的东西,不允许写异步代码。
  • action
    它里面可以写异步代码,它如果要修改 state 数据,是通过去调用 mutation。
  • module
    仓库模块的拆分,当项目足够大的时候应该把vuex分成多个子模块。
    仓库子模块其实就是一个包含有 state 、getters、mutations、actions 的对象

使用vuex

  1. 项目安装vuex
npm install vuex
  1. 在 src 目录下创建一个store的文件夹并在里面创建一个index.js文件和modules的文件夹,这样可以较好的区分子模块。如图:
    在这里插入图片描述
    在index.js里实例化 Vuex 的一个 store仓库实例对象并暴露出去。

仓库根模块

// 1. 引入 Vue
import Vue from "vue";

// 2. 引入 Vuex
import Vuex from "vuex";

// 引入拆分出来的仓库子模块()
//仓库子模块其实就是一个包含有 state 、getters、mutations、actions 的对象
import moduleA from "./modules/a模块";
import moduleB from "./modules/b模块";

// 3. 调用
Vue.use(Vuex);

// 4. 生成 仓库 实例对象
const store = new Vuex.Store({
  // 配置 modules
  modules: {
    a: moduleA,
    b: moduleB,
  },
});
// end. 暴露 store
export default store;

仓库子模块 module

  1. 仓库拆分子模块之后,没有设置命名空间。有一些问题的
    1. 多个仓库子模块中的 getter 不能同名,否则会报错
    2. 多个仓库子模块中的 mutation 如果同名的化,组件调用这个 mutation 时。都会被触发, 会有污染的风险
    3. 多个仓库子模块中的 action 如果同名的化,组件调用这个 action 时。都会被触发, 会有污染的风险
  2. 由于有上面的这种问题存在,所以推荐仓库子模块都设置上命名空间。
    给仓库子模块的 那个对象配置一个 namespaced 属性。属性值为 true
// 拆分的仓库子模块A
const moduleA = {
  namespaced: true, //仓库子模块的命名空间
  state: { 
	name: '张三'
  },
  mutations: { 
  //mutations会自动接收 state, payload是传过来的值 
	SET_NAME(state, payload) {
		state.name = payload
	}
  },
  actions: { 
  //actions会自动接收 content, payload是传过来的值 
	SYNC_SET_NAME(content, payload){
		setTimeout(() => {
        // 调用 SET_NAME 这个 mutation 来修改 state 数据
        context.commit("SET_NAME", payload);
      }, 2000);
	}
 },
  getters: { 
	firstName(state, pa) {
		//getters会自动接收 state
		return state.name.substr(0,1);
	}
 },
  // 仓库子模块也可以继续去做拆分,但是没必要搞这么复杂
  modules: { ... }
}
export default moduleA;
  1. 需要在 src目录下的main.js 文件的 new Vue() 的位置去配置 store 选项,选项值是上一个步骤中暴露出来的 store 的实例。
import Vue from "vue";
import App from "./App.vue";
import store from "./store";//index可以省略

Vue.config.productionTip = false;//这个是阻止启动生产消息设不设置看你喜欢

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

三、使用 state 与 getter

一、使用挂载到 Vue原型上的 $store 对象。这个 $store 就是 new Vuex.Store() 生成的仓库实例对象

//在组件里用 (建议在组件的 computed 里用)
this.$store.state['a/name'] //moduleA的state a代表的是moduleA的命名 
this.$store.getters['a/firstName'] //moduleA的getters a代表的是moduleA的命名

//用在组件上
<h1>{{ $store.state['a/name'] }}</h1> 输出结果为张三
<h1>{{ $store.state['a/firstName'] }}</h1>  输出结果为张

二、使用 vuex 提供的辅助函数

// 引入 辅助函数 。采用类似解构赋值的方式
import { mapState, mapGetters } from 'vuex'
//在组件的 computed 里用
computed: {
	//辅助函数返回值是一个对象,需要用扩展运算符展开
	//辅助函数接收一个数组做为参数,参数中的每一项就是该辅助函数对应在仓库中的值 有命名空间的仓库模块要在第一个参数里写上命名
	...mapState('a', ['name']), a是moduleA的命名 name是要用的state里的数据 
	...mapGetters('a', ['firstName']) 
}

//用在组件上
<h1>{{ name }}</h1>输出结果为张三
<h1>{{ firstName }}</h1>输出结果为张
}

四、修改 state 与 getter 数据

首先明确一点。state 可以修改。getter 不能修改。
1. 仓库中要提供 对应 state 修改的 mutation 函数
2. 在组件中去调用 mutation

一、在组件中先定义一个函数,使用 vuex 绑定到 vue 原型上的 $store 这个对象的 commit() 方法

methods: {
  SET_NAME(name) {
   	this.$store.commit('a/SET_NAME', name);
  }
}


//用在组件上
<h1>{{ $store.state['a/name'] }}</h1> 点击后输出结果为李四
<h1>{{ $store.state['a/firstName'] }}</h1> 点击后输出结果为李
<button @click="SET_NAME('李四')">修改name</button>

二、使用 mapMutations 辅助函数

// 引入 辅助函数 。采用类似解构赋值的方式
import { mapState, mapGetters, mapMutations } from 'vuex'
computed: {
	...mapState('a', ['name']), a是moduleA的命名 name是要用的state里的数据 
	...mapGetters('a', ['firstName']) 
}
methods: {
	...mapMutations('a', ['SET_NAME']) a是moduleA的命名 SET_NAME是mutations要用的里的函数 
}


//用在组件上
<h1>{{ name }}</h1> 点击后输出结果为李四
<h1>{{ firstName }}</h1> 点击后输出结果为李
<button @click="SET_NAME('李四')">修改name</button>

五、异步修改 state

首先需要知道,mutation 里面只允许同步的去修改 state 数据。(虽然在mutation中可以异步的去修改state数据不会报错,但是会导致时间旅行等机制没有效果)

如果异步的修改的话,有两个大方案

  1. 不涉及action。在组件上异步代码走完之后再去调用 mutation
  2. 使用 action
  • action 类似于 mutation,不同在于:
    1. action 提交的是 mutation,而不是直接变更状态。
    2. action 可以包含任意异步操作。

使用 action 异步的修改 state 数据

// 步骤和上面差不多
// 1. 通过 $store 上的 dispatch 方法
this.$store.dispatch('ma/SYNC_SET_NAME', payload)
// 2.mapActions辅助函数
methods: {
  ...mapActions('a', ['SYNC_SET_NAME'])
}

结尾、建议使用 vueDevtools 来辅助开发,如图:

用 vueDevtools 就可以观察到仓库中的数据
在这里插入图片描述

原创文章 11 获赞 259 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yh604005215/article/details/105588059