钉钉小程序自定义store状态插件

301 阅读1分钟

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,入参