Vuex模块化应用实践示例
Vuex作为Vue全家桶的成员之一,重要性肯定不用多说,正在做Vue项目的同学,随着项目需求、功能逐渐增加,用到Vuex也是早晚的事儿,作为一个前端,只能面对现实:学不动也得学!
成都创新互联公司是一家集网站建设,宁安企业网站建设,宁安品牌网站建设,网站定制,宁安网站建设报价,网络营销,网络优化,宁安网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
这篇文章主要介绍Vuex在大型项目中的模块化及持久化应用实践,下面正文开始
Vuex的应用场景
- 多个组件视图共享同一状态时(如登录状态等)
- 多个组件需要改变同一个状态时
- 多个组件需要互相传递参数且关系较为复杂,正常传参方式变得难以维护时
- 持久化存储某些数据
所以我们把组件共享的状态抽离出来,不管组件间的关系如何,都通过Vuex来处理
组织store目录
我们先按模块化的方式组织store目录,并在Vue根实例中注册store,Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中
src ├── ... ├── main.js ├── App.vue └── store ├── index.js # 我们组装模块并导出 store 的地方 └── modules ├── product.js # 产品模块 ├── windowInfo.js # 窗口信息模块 └── user.js # 登录模块
src/store/index.js
import Vue from 'vue' import Vuex from 'vuex' import user from './modules/user' import product from './modules/product' import windowInfo from './modules/windowInfo' Vue.use(Vuex) export default new Vuex.Store({ modules: { // 注册modules中的模块 user, product, windowInfo } })
src/main.js
import ... import store from './store' // 添加这行 new Vue({ el: '#app', router, store, // 注入到根实例 template: '', components: { App } })
store的属性
state(状态对象)
state中存放多页面共享的状态字段
getters
相当于当前模块state的计算属性
mutations
如果想更新state中的字段,提交mutations中定义的事件是唯一的方式(key为事件名,value是一个函数),但是这个事件函数必须是同步执行的
actions
可以定义异步函数,并在回调中提交mutation,就相当于异步更新了state中的字段
vuex数据传递规则
使用方法
把窗口的高度和宽度存到Vuex中,并且每当窗口被resize,state中的高度和宽度自动更新
src/store/modules/windowInfo.js
import { MU_WIN_RESIZE } from '../../common/constants' const windowInfo = { state: { // 初始化 winHeight: 0, winWidth: 0 }, mutations: { // 这里把事件名统一抽离到constants.js统一管理,方便维护,避免重复。 // 当然,你也可以不这么写。。 // mutation事件接受的第一个参数是当前模块的state对象 // 第二个参数是提交事件时传递的附加参数 [MU_WIN_RESIZE] (state, payload) { const { winWidth, winHeight } = payload state.winWidth = winWidth state.winHeight = winHeight } }, actions: {}, getters: {} } export default windowInfo
src/common/constants.js
export const MU_WIN_RESIZE = 'MU_WIN_RESIZE' // 更新窗口尺寸
下面打开项目的根组件添加监听resize事件和提交mutation事件逻辑
src/App.vue
到这一步,在拖动窗口触发‘resize'事件的时候,就会触发‘MU_WIN_RESIZE'这个mutation事件并把窗口宽高写入vuex,下面我们随便找个页面看能不能获取到我们写入的值
窗口高:{{winHeight}} 窗口宽:{{winWidth}}
有的时候我们会从后端获取一些下拉框选项的静态常量,而且很多页面都能用到,这个时候用Vuex是比较好的选择,涉及到后端获取,就要用到可以使用异步的actions了
src/store/modules/product.js
import {MU_PRODUCT_UPDATE_CONSTANTS} from '../../common/constants' const product = { state: { productConstants: [] }, mutations: { [MU_PRODUCT_UPDATE_CONSTANTS] (state, payload) { state.productConstants = payload } }, actions: { // action函数第一个参数接受一个与 store 实例具有相同方法和属性的 context 对象, // 因此你可以调用 context.commit 提交一个 mutation, // 或者通过 context.state 和 context.getters 来获取 state 和 getters // 这里虽然能获取到state,但是不建议直接修改state中的字段 async getProductConstants ({ commit }, payload) { try { // 请求接口,如果需要参数可以通过payload传递 const res = await this.$api.product.getConstants() commit(MU_PRODUCT_UPDATE_CONSTANTS, res) } catch (e) { console.error(e) } } }, getters: {} } export default product
下面触发这个getProductConstants事件,触发这个action事件的位置需要注意一下,假设你有5个组件需要使用这个state,那就应该在这5个组件共同的父组件中调用一次action(找不到就在根实例中调用),然后在各个子组件中通过mapState或mapGetters获取state,千万不要每个组件使用前都调用一次action方法!
src/App.vue
mapGetters, mapMutations, mapActions,这几个函数可以接受对象也可以接受数组作为参数,如果你需要在组件中以别的名字调用该事件(像上面的mapMutations)就可以传入对象,key为新命名,value是store中定义的名字;否则的话传数组就好了。
那么问题来了,既然是异步操作,我想在操作结束后干点儿别的怎么做呢?
很简单,调用action中的异步函数(this.$store.dispatch)返回的是一个Promise,如果你跟我一样用的是async await:
如果你用的不是async await那就麻烦一点,在actions中定义事件的时候return一个new Promise,官方文档中有一个例子
表单处理
当你把从state中获取的字段填在v-model中时,如果用户修改表单数据,v-model会尝试直接修改store中的数据,这样做会有两个问题:
- 破坏了vuex的数据传递规则,如果想修改state中的数据只能通过提交一个mutation
- 控制台报错:计算属性没有setter
官方提供了两种解决方法,我更倾向于下面这种,给计算属性添加setter,并在setter中提交mutation修改state:
Vuex持久化
推荐插件vuex-persist
安装插件:
npm install --save vuex-persist
引入、配置、加载插件:
src/store/persist.js
import VuexPersistence from 'vuex-persist' const persist = new VuexPersistence({ // 其他参数看文档 storage: window.sessionStorage }) export default persist.plugin
src/store/index.js
import ... import persist from './persist' Vue.use(Vuex) export default new Vuex.Store({ modules: { user, product, windowInfo }, plugins: [persist] })
现在刷新浏览器数据也不会重置了!
总结
以上就是vuex比较常规的操作了,第一次看官方文档的我是懵逼的、无助的,但是用了一段时间vuex再重新看文档的时候会有很多收获。希望对大家的学习有所帮助,也希望大家多多支持创新互联。
分享文章:Vuex模块化应用实践示例
文章位置:http://azwzsj.com/article/jhgeed.html