目录:
- 简介
- Vuex原理图
- 基本用法
一、简介
1.1、Vuex的概念和作用
Vuex 是一个专为 Vue.js 引用程序并发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式放生变化。简单来说:Vuex是用来集中管理数据,类似于React中的Redux(回来,回家),都是基于Flux(融化了)的前端状态管理框架。Vuex 一般小项目,写两个页面是用不到的,但是中大型项目是需要用到的。
1.2、访问Vuex官网方式
1.Vuex的官网:https://vuex.vuejs.org/zh/
2.也可以通过 Vue.js 官网进入 Vuex的官网:生态系统 -> 核心插件 -> Vuex
1.3、什么是组件状态?
比如说你的组件会有不同的状态,这个状态比如说显示或者隐藏,或者你的数据的需要展示,你的数据管理等等,都可以使用Vuex来操作。
1.4、Vuex在集中管理数据起到什么作用?
集中管理数据的,你的项目当中很多数据需要管理,包括你的组件间需要数据的传递,传递的方式我们也可以用不同的方式,如:父子组件的数据传递(props和触发事件),非父子组件的数据传递(中央总线方式)。但是如果说你的项目太复杂,以组件的方式传递数据,用这种方式特别费劲,而且很乱。项目真的变大了之后,这种单线传递太麻烦了,所以现在基本都用Vuex。但是你的项目很简单,没有必要使用Vuex。
二、Vuex的原理图
这个原理图在官网也有,只不过我说明了一下。官网管理图
原理图说明:
1. Vue组件上操作,会发出(dispatch)一个动作(actions) -> 2. 提交(commit) 改变(mutation)的数据 -> 3.突变或者说改变(mutate) 状态(state)中的数据 -> 4.改变之后,重新渲染(render)组件(Vue Components) ->5.组件就会更新,展示更新过后的数据。
三、基本使用
3.1、安装Vuex
>npm install vuex -S
3.2、目录结构
|-vuex-demo |-node-modules |-src |-assets |-App.vue |-main.js |-store.js //vuex的相关配置都在store.js中 |-.babelrc |-... |-webpack.config.js
3.3、创建store.js文件,在main.js中导入并且配置store对象
说明:Vuex的相关配置都在这个里面配置的
import Vue from 'vue' import App from './App.vue' import store from './store.js' //导入store对象 new Vue({ el: '#app', render: h => h(App), //配置store选项,指定为store对象,会自动将store对象注入到所有子组件中(Vue实例是根组件,其他的都是子组件),在子组件中通过this.$store访问store对象 store //(缩写) store:store,导入Vuex后就有store这么一个选项,store值就是你导入的store });
注意了:Vue实例是根组件,Vue实例下注册的组件,都是vue根组件下的子组件。
3.4、编辑 store.js
Vuex的核心是store(仓库),相当于一个容器,一个store实例中包含以下属性方法:
state: 定义属性(状态、数据) getters: 用来获取属性 actions: 定义方法(动作) commit: 提交变化,修改数据的唯一方式就是现实的提交mutations mutations: 定义变化(或突变),来改变数据
注:不能直接修改数据,必须是显式提交变化,目的是为了追踪到状态的变化
store.js的内容(方式1:通过this.$store访问) :
/* * Vuex 配置 * */ import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); //1.定义属性(数据) var state={ count:6 }; //2.创建store对象 const store = new Vuex.Store({ state //(缩写) state:state }); //3.导出store对象 export default store;
store.js的内容(方式2:通过mapGetters、mapActions访问) :
/* * Vuex 配置 * */ import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); //1.定义属性(数据) let state={ count:6 }; //2.定义getters let getters = { count(state){ //参数state就是上面的state return state.count; } }; //3.定义actions,要执行的操作,如流程判断,一部请求等 const actions = { /*increment(context){ //对应的increment的就是App.vue中绑定的事件 console.log(context); }*/ increment({commit,state}){ //es6的语法 commit('increment'); //提交(commit)一个名为increment的变化,名称自定义,可以认为是类型名 } }; //4.定义mutations处理状态(数据)的改变 const mutations = { increment(state){ //increment函数名必须跟 actions中的commit是一样的 state.count++; } }; //5.创建store对象 const store = new Vuex.Store({ state, //(缩写) state:state getters, actions, mutations }); //6.导出store对象 export default store;
我们先来看看actions是中的context有哪些东西:
▼{getters: {…}, state: {…}, rootGetters: {…}, dispatch: ƒ, commit: ƒ, …} ▶dispatch: ƒ boundDispatch(type, payload) ▶commit: ƒ boundCommit(type, payload, options) ▶getters: {} ▶state: {__ob__: Observer} ▶rootGetters: {} ▶rootState: {__ob__: Observer} ▶__proto__: Object
很明显是一个对象,但是我们用es6的语法使用,不然用起来比较麻烦!!!
3.5、编辑App.vue
在子组件中访问store对象的两种方式:
方式1:通过this.$store访问
方式2:通过MapState、mapGetters、mapActions访问,Vuex提供了2个方法:
MapState:获取state mapGetters: 获取getters,获取属性(数据) mapActions: 获取actions,获取方法(动作)
App.vue编辑(方式1:通过this.$store访问)
<template> <div id="app"> <!--获取计算属性count--> <p>当前数据为:{{count}}</p> </div> </template> <script> export default { name: 'app', //方式1: 通过this.$store访问 computed:{ count(){ return this.$store.state.count; } } } </script>
App.vue编辑(通过mapGetters、mapActions访问)
<template> <div id="app"> <!--触发事件--> <button @click="increment">增加</button> <!--获取数据--> <p>当前数据为:{{count}}</p> </div> </template> <script> //先导入mapState(匹配state),mapGetters(匹配属性),mapActions(匹配方法)方法 import {mapState,mapGetters,mapActions} from 'vuex' export default { name: 'app', //方式2:通过mapGetters、mapActions访问 //computed:mapGetters([ // 'count' //对应的store.js中的getters中的count()方法 //]), computed:mapState([ 'count' //对应就是state中的count ]), methods:mapActions([ 'increment' //匹配store.js中的actions中的increment方法 ]) } </script>
通过mapState或者mapGetters都可以获取count值,这个就要看你喜欢用什么了,只不过mapState是直接获取 state中的值,而mapGetters是通过定义方法获取,而且用getters,来获取处理过的数据不一定就是直接的count,例子下面代码练习有。
3.6、Vuex的练习所有代码
说明:main.js就直接引用上面的,其他的完整练习代码如下,这边特别注意的是:我们在调代码的时候 可以 配合 vue-devtools 配合使用,使用方法:1-1 基本用法-第一个vue程序
1、App.vue组件
<template> <div id="app"> <button @click="increment">增加</button> <button @click="decrement">减少</button> <button @click="incrementAsync">增加</button> <!--获取数据--> <p>当前数据为:{{count}}</p> <p>{{isEvenOrOdd}}</p> </div> </template> <script> import {mapState,mapGetters,mapActions} from 'vuex' export default { name: 'app', //方式2:通过mapGetters、mapActions访问 computed:mapGetters([ 'count', //对应的store.js中的getters中的count()方法 'isEvenOrOdd' ]), // computed:mapState([ // 'count' //对应就是state中的count // ]), methods:mapActions([ 'increment', 'decrement', 'incrementAsync' ]) } </script> <style> </style>
2、store.js代码:
/* * Vuex 配置 * */ import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); //1.定义属性(数据) let state={ count:6 }; //2.定义getters let getters = { count(state){ //参数state就是上面的state return state.count; }, isEvenOrOdd(state){ //getters,来获取处理过的数据不一定就是直接的count return state.count%2 == 0?'偶数':'奇数'; } }; //3.定义actions,要执行的操作,如流程判断,一部请求等 const actions = { /*increment(context){ //对应的increment的就是App.vue中绑定的事件 console.log(context); }*/ increment({commit,state}){ //es6的语法 commit('increment'); //提交(commit)一个名为increment的变化,名称自定义,可以认为是类型名 }, decrement({commit,state}){ //在提交条件这边做判断 if(state.count>10){ commit("decrement"); } }, incrementAsync({commit,state}){ //异步操作 let p = new Promise((resolve,reject) => { setTimeout(() => { resolve(); },3000); }); p.then(()=> { commit('increment'); //状态改变可以是同一个操作 }).catch(() => { console.log('异步操作'); }); } }; //4.定义mutations处理状态(数据)的改变 const mutations = { increment(state){ //increment函数名必须跟 actions中的commit是一样的 state.count++; }, decrement(state){ state.count--; } }; //5.创建store对象 const store = new Vuex.Store({ state, //(缩写) state:state getters, actions, mutations }); //6.导出store对象 export default store;
实现界面如下:
当前数据为:6
偶数