1.背景
由于小程序没有前端状态管理工具,在页面与页面之间数据交互比较复杂的情况下,急需要有这样的工具,能够统一定义状态名、状态存、取、初始化等。
2.wedux
具体实现如下,入参props是其配置信息。暂时不支持异步的存取(业务上暂时不需要)。
props={store, actions, accesses}
store:{},存放的初始化状态信息
actions:[],存放的是所有可选的操作,存数据、改数据
accesses:[],存放的是所有可读数据的操作,返回的是需要的状态值
$dispatch
用于分发action,入参有actionName和payload,其中actionName是要分发的action的名称,payload是这个action执行需要的参数。
wedux拿到actionName会从actions列表拿到对应的action,并将参数传进去,执行。
$store
存真正执行的操作,这里只支持同步,若是异步的话,需要通过实践循环队列依次取更新store,避免数据读写冲突。
从代码来看,非常的简单,就是store[storeName] = v 。入参就是storeName(待修改状态的名称)和v(修改后的值)。
$store是内部使用的代码
$get
取操作,入参accessName,wedux拿到accessName后会重accesses列表中找到对应的取方法,并执行,将要取的数据返回。
//仅支持同步
export default class wedux {
constructor(props = {}) {
const { store, actions, accesses } = props
this.store = store || {}
this.actions = actions || {}
this.accesses = accesses || {}
}
//发布action
$dispatch(actionName, payload) {
if (!this.actions[actionName]) {
console.error(`未注册名为:${actionName}的action`)
return
}
this.actions[actionName](payload, { set: this.$store, store: this.store })
}
//存操作
$store(storeName, v, store) {
store[storeName] = v
console.log(store)
}
//取操作,accessName是在配置项中定义的取操作名称
$get(accessName) {
if (!this.accesses[accessName]) {
console.error(`不存在名为${accessName}的取操作`)
return
}
const v = this.accesses[accessName]({ store: this.store })
// console.log(`${accessName}的值:`, v)
return v
}
}
3.配置如下
个人比较懒 直接把项目中代码附上了。
export const storeConfig = {
store: {
//注册学生
'regist.st.current': 'tab1',
'regist.st.auto': {
institution: {
orgId: null,
orgName: null
},
acc: null,
pwd: null,
},
'regist.st.bymobile': {
institution: {
orgId: null,
orgName: null
},
acc: null,
pwd: null,
},
//注册老师
'regist.tc.current': 'tab1',
'regist.tc.auto': {
institution: {
orgId: null,
orgName: null
},
acc: null,
pwd: null,
},
'regist.tc.bymobile': {
institution: {
orgId: null,
orgName: null
},
acc: null,
pwd: null,
},
//体验课程
'enroll.current': 'tab1',
'enroll.exp': {
institution: {
orgId: null,
orgName: null,
},
students: {
},
days: null,
course: null
},
//正式课程
'enroll.offi': {
institution: {
orgId: null,
orgName: null,
},
students: {
},
days: null,
course: null
}
},
//事件处理操作
actions: {
//注册时选择机构
InstitutionSetWhenRegistStudentAuto(paylod, { set, store }) {
store['regist.st.auto'].institution = paylod
set('regist.st.auto', store['regist.st.auto'], store)
},
//注册学生账号或教师账号,设置密码
accNumSetWhenRegist(paylod, { set, store }) {
console.log('accNumSetWhenRegist', paylod)
const { type, acc } = paylod
switch (type) {
case '00': //学生-自动
store['regist.st.auto'].acc = acc
set('regist.st.auto', store['regist.st.auto'], store)
break;
case '01'://学生--手机号
store['regist.st.bymobile'].acc = acc
set('regist.st.bymobile', store['regist.st.bymobile'], store)
break;
case '10'://教师-自动
store['regist.tc.auto'].acc = acc
set('regist.tc.auto', store['regist.tc.auto'], store)
break;
default: //教师--手机号
store['regist.tc.bymobile'].acc = acc
set('regist.tc.bymobile', store['regist.tc.bymobile'], store)
}
},
pwdSetWhenRegist(paylod, { set, store }) {
const { type, pwd } = paylod
switch (type) {
case '00': //学生-自动
store['regist.st.auto'].pwd = pwd
set('regist.st.auto', store['regist.st.auto'], store)
break;
case '01'://学生--手机号
store['regist.st.bymobile'].pwd = pwd
set('regist.st.bymobile', store['regist.st.bymobile'], store)
break;
case '10'://教师-自动
store['regist.tc.auto'].pwd = pwd
set('regist.tc.auto', store['regist.tc.auto'], store)
break;
default: //教师--手机号
store['regist.tc.bymobile'].pwd = pwd
set('regist.tc.bymobile', store['regist.tc.bymobile'], store)
}
},
InstitutionSetWhenRegistStudentByMobile(paylod, { set, store }) {
store['regist.st.bymobile'].institution = paylod
set('regist.st.bymobile', store['regist.st.bymobile'], store)
},
InstitutionSetWhenRegistTeacherAuto(paylod, { set, store }) {
store['regist.tc.auto'].institution = paylod
set('regist.tc.auto', store['regist.tc.auto'], store)
},
InstitutionSetWhenRegistTeacherByMobile(paylod, { set, store }) {
store['regist.tc.bymobile'].institution = paylod
set('regist.tc.bymobile', store['regist.tc.bymobile'], store)
},
SetTabInRegistStudent(payload, { set, store }) {
set('regist.st.current', payload, store)
},
SetTabInRegistTeacher(payload, { set, store }) {
set('regist.tc.current', payload, store)
},
//获取课程报名时选择的机构,设置
InstitutionWhenEnroll(payload, { set, store }) {
const { orgName, orgId } = payload
if (payload.type === 0) { //默认体验课程
store['enroll.exp'].institution = { orgId, orgName }
set('enroll.exp', store['enroll.exp'], store)
} else { //正式课程
store['enroll.offi'].institution = { orgId, orgName }
set('enroll.offi', store['enroll.offi'], store)
}
},
daysWhenEnroll(payload, { set, store }) {
if (payload.type === 0) {
store['enroll.exp'].days = payload.days
set('enroll.exp', store['enroll.exp'], store)
} else {
store['enroll.offi'].days = payload.days
set('enroll.offi', store['enroll.offi'], store)
}
},
studentsWhenEnroll(payload, { set, store }) {
const { institutionId, type } = payload
if (institutionId) {
if (institutionId === 'null') {
console.error(`请确定institutionId,再保存学生`)
return
}
if (type === 0) {
store['enroll.exp'].students[institutionId] = payload.students
set('enroll.exp', store['enroll.exp'], store)
} else {
store['enroll.offi'].students[institutionId] = payload.students
set('enroll.offi', store['enroll.offi'], store)
}
} else {
console.error(`请确定institutionId,再保存学生`)
}
},
//选择的课程保存
courseWhenEnroll(payload, { set, store }) {
console.log('courseWhenEnroll')
if (payload.type === 0) {
store['enroll.exp'].course = payload.course
set('enroll.exp', store['enroll.exp'], store)
} else {
store['enroll.offi'].course = payload.course
set('enroll.offi', store['enroll.offi'], store)
}
},
//课程开始时间设置
startTimeWhenEnroll(payload, { set, store }) {
store['enroll.offi'].startTime = payload.time
set('enroll.offi', store['enroll.offi'], store)
},
//课程结束时间设置
endTimeWhenEnroll(payload, { set, store }) {
store['enroll.offi'].endTime = payload.time
set('enroll.offi', store['enroll.offi'], store)
},
setTabWhenEnroll(payload, { set, store }) {
set('enroll.current', payload, store)
}
},
//取操作{取操作名称:返回对应状态的方法}
accesses: {
//选择机构结果
Insitution_St_Regist_Auto({ store }) {
return store['regist.st.auto']
},
Insitution_St_Regist_Bymobile({ store }) {
return store['regist.st.bymobile']
},
Insitution_Tc_Regist_Auto({ store }) {
return store['regist.tc.auto']
},
Insitution_Tc_Regist_Bymobile({ store }) {
return store['regist.tc.bymobile']
},
Tab_Regist_St_Page({ store }) {
return store['regist.st.current']
},
Tab_Regist_Tc_Page({ store }) {
return store['regist.tc.current']
},
//体验课程
Tab_Enroll({ store }) {
return store['enroll.current']
},
Enroll_Exp_Data({ store }) {
return store['enroll.exp']
},
Enroll_Offi_Data({ store }) {
return store['enroll.offi']
},
}
}
4.使用
存放在globalData全局变量之下,每次使用的时候,只需从全局变量中取wedux即可。
import wedux, { storeConfig } from './util/store.js'
App({
globalData: {
hasLogin: false,
wedux: new wedux(storeConfig)
},
});
工具方法getWedux()用于获得全局的wedux。
export const getWedux = () => {
const app = getApp()
const { wedux } = app.globalData
return wedux
}
//使用案例
const wedux = getWedux()
wedux.$get('Enroll_Offi_Data') //找到一个叫Enroll_Offi_Data的取操作执行后的结果,并返回
wedux.$dispatch('courseWhenEnroll', { course: EnrollOptions, type }) //分发一个叫courseWhenEnroll的操作,修改store
5.可优化的点
(1) store的配置根据需求和应用的复杂度,可以配置成按模块配置的,未来可做优化项
(2) 针对异步操作,未来可做优化项
(3) 取数据$get方法,可以增加payload,入参