vue之使用vuex进行状态管理详解
作者:巴啦啦小能量
这篇文章主要介绍了vue之使用vuex进行状态管理详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
vuex进行状态管理
首先学习vuex必须先知道vue原理
Vue是一个典型的MVVM框架,模型(Model)只是普通的JavaScript对象,修改它则视图(View)会自动更新。这种设计让状态管理变得非常简单而直观
Vue实现这种数据双向绑定的效果,需要三大模块:
Observer
:能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者Compile
:对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数Watcher
:作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
大概分为这么几类
vuex是什么呢
vuex是实现状态管理的工具 可以用来管理大型项目的工具
下面是一个简单的vuex的结构
index是主文件
//index// import Vue from 'vue' import Vuex from 'vuex' import * as getters from './getters' import * as actions from './actions' import * as mutations from './mutations' Vue.use(Vuex) const state = { username: '123' } const store = new Vuex.Store({ state, getters, actions, mutations }) export default store
进行一个简单地账户管理
//actions文件 // 给action注册事件处理函数。当这个函数被触发时候,将状态提交到mutations中处理 export function modifyAName({commit}, name) { // commit 提交;name即为点击后传递过来的参 return commit ('modifyAName', name) } // ES6精简写法 //export const modifyAName = ({commit},name) => commit('modifyAName', name) //motations文件 // 提交 mutations是更改Vuex状态的唯一合法方法 export const modifyAName = (state, name) => { // A组件点击更改餐馆名称为 A餐馆 state.resturantName = name // 把方法传递过来的参数,赋值给state中的resturantName } //getters文件 // 获取最终的状态信息 export const resturantName = state => state.resturantName //组件A/methods函数 sub(){ let log = document.querySelector("#log").value; let reg = document.querySelector("#reg").value; userapi("/users/userpsw",{name:log,psw:reg}, (mes) => { if(mes === 1){ console.log(log) this.$store.commit("modifyAName",log) // 账户名称 console.log(this.$store.getters.resturantName) document.querySelector(".text").innerHTML = "登录成功" this.$router.push({ path: '/my' }) }else{ document.querySelector(".text").innerHTML = "登录失败" } }) }, 组件B/computed computed:{ username(){//调用username即可 {{username}} return this.$store.getters.resturantName } },
vuex状态管理基本使用
通过npm安装vuex
npm install vuex --save
使用vuex
import Vuex from 'vuex' Vue.use(Vuex) //赋值给一个变量,然后引入 let store = new Vuex.Store({ ... }) //为了更好的维护,且体现模块化,可以写在别的js文件中,然后导入 import store from './store' //创建一个store文件夹,默认为文件夹下的index.js文件 new Vue({ ... store, ... })
使用vuex基本结构
new Vuex.Store({ //状态 state: { count: 100 }, //将状态装饰,或刷选,以想要的结果输出 getters: { hasUnit () { return this.state.count.filter(count => count + 1) } }, //可以理解为变更状态的方法,第一个参数为state,可以再添加自定义参数,注意:只能进行同步 mutations: { increment (state) { state.count++ } }, //可控制的提交mutation事件,弥补mutation无法异步 actions: { increment (state) { setTimeout(() => state.commit('increment'), 30) } } })
为了更好的维护,往往将store文件写成以下结构 ,名字自定义,但是需要知道每个文件的作用
index.js
:主要作为导出store,作为汇总的文件state.js
:作为定义的变量集合,作为一个对象导出getters.js
:作为主要是获取state中变量值的方法,return出state相应的值,或者length等等的一些state变量的信息mutations-type.js
: 作为一些方法等命名的变量,防止书写错误
mutaintions.js
:存放修改state变量的同步方法,这里可以的方法名就是用了mutations-type.js中的变量命名,[object.value]这种方式是ES6中的语法
action.js
:存放修改state变量的异步方法
在组件中引用,不使用mapXXXXX辅助函数情况下
state和getter:直接在computed计算属性中使用
computed: { count () { return this.$store.state.count }, hasUnit () { return this.$store.getters.hasUnit } }
mutations和actions则被作为事件调用,可以放在methods,watch等等,有事件调用的时候都可以
methods: { add () { this.$store.commit('increment') // mutations使用commit调用 }, asyncAdd () { this.$store.dispatch('increment') // actions使用dispatch调用 } }
通过mapXXXX辅助函数来引用
先确保组件中已导入vuex的相应辅助函数:用到哪个导入哪个
import { mapState } from 'vuex' import { mapGetters } from 'vuex' import { mapMutations } from 'vuex' import { mapActions } from 'vuex' //导入多个:ES6模块 import { mapState, mapGetters } from 'vuex'
然后根据你的需求使用对应的辅助函数,前提是已经导入
computed: { ...mapState([ 'count' ]), ...mapGetters([ 'addUnit' ]) } //使用this.count, this.addUnit
methods: { ...mapMutations([ 'increment' ]), ...mapActions({ addNum: 'increment' }) add () { this.increment() } } //可以被当做事件调用,为了避免命名冲突,可以使用重命名,需要使用{}而不是[]
模块:Module
当项目很大的时候,很多版块在一起容易混淆,希望每个版块的信息归每个版块下面,易于维护
//局部模块引用的第一个参数state都是自己模块里的 const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } })
以moduleA为例 ,可以新建一个JS文件,然后通过import导入到总的vuex管理中
const state = { count: 1 }; const getters = { get(state) { return state.count; } }; const mutations = { add(state) { state.count++; }, reduce(state) { state.count--; } }; const actions = { add: ({ commit }) => { commit("add"); }, reduce: ({ commit }) => { commit("reduce"); } }; export default { namespaced: true, // 使该模块带有命名空间,使它在命名上会按路径进行命名 如moduleA/state state, getters, mutations, actions };
在使用了模块后,我们可以通过以下方式获取,这里只用了辅助函数展示
computed: { ...mapState({ count: state => state.moduleA.count }), ...mapGetters({ get: "moduleB/get" }) }
methods: { ...mapMutations( 'moduleA', {addA:'add', reduceB:'reduce'} // 重命名就用对象包裹 ), ...mapActions( 'moduleA', ['add', 'reduce'] ) }
如果想引用根目录下的状态,需要传入第三个参数
const moduleA = { // ... getters: { addUnit (state, getters, rootState) { //rootState为根下的状态 return state.count + rootState.count } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。