之前是把全局状态和局部状态放在一起定义了,但是使用一段时间之后发现,没有必要放在一起,既然局部状态不需要一开始就调用,那么也就没有必要非得放在插件里面。
我们可以按照“充血实体类”的思路来单独设计模块状态。
模块结构
我们以常见的列表功能为例介绍一下。
数据列表页面列表页面可以分为:查询、列表、分页和操作按钮以及弹窗表单几个部分组成。
按照原子级别的划分方式,以上这些部分可以分为多个组件,这样就需要一个状态负责消息传递。
状态包括且不限于:数据、方法、事件、监听、生命周期等。
定义模块状态
建立一个 state-list.js 文件,便于复用。先定义状态的结构。
// 列表功能需要的状态
const state = reactive({
query: {}, // 用户输入的查询条件
fixedQuery: {}, // 固定的查询条件,比如 isdel = 0
pager: { // 分页参数
pagerTotal: 100, // 0:需要统计总数;其他:不需要统计总数
pagerSize: 5, // 一页记录数
pagerIndex: 1, // 第几页的数据,从 1 开始
orderBy: { id: false } // 排序字段
},
choice: { // 列表里面选择的记录
dataId: '', // 单选,便于修改和删除
dataIds: [], // 多选,便于批量删除
row: {}, // 选择的记录数据(单选),仅限于列表里面的。
rows: [] // 选择的记录数据(多选),仅限于列表里面的。
},
hotkey: () => {}, // 处理快捷键的事件,用于操作按钮和分页
reloadFirstPager: () => {}, // 重新加载第一页,统计总数(添加后)
reloadCurrentPager: () => {}, // 重新加载当前页,不统计总数(修改后)
reloadPager: () => {} // 重新加载当前页,统计总数(删除后)
})
- reactive
使用 reactive 来定义状态,可以保证响应性。
内部是一个大的属性集合,模块需要的属性都可以放在这里集中管理。
这里是以列表组件为例,其他模块可以设置其他的属性。
定义方法
/**
* 设置功能
*/
const setFunction = () => {
// 重新加载第一页,统计总数(添加、查询后)
state.reloadFirstPager = () => {
...
}
watch(() => state.pager.pagerIndex, (v1, v2) => {
...
})
}
可以集中设置需要的各种方法、事件还有watch、生命周期等。
这样不容易乱。
注入(注册和提取)
然后要把状态注入进去,这个也可以封装一下:
/**
* 父组件注册状态
* @returns 注册列表状态
*/
const regState = () => {
// 初始设置
setFunction()
provide(flag, state)
return state
}
/**
* 子组件获取状态
* @returns 注册列表状态
*/
const getState = () => {
const _state = inject(flag)
if (typeof _state === 'undefined') {
// 没有找到状态
return null
} else {
// 找到了,返回
return _state
}
}
-
regState
在父组件使用 regState 方法,注入状态,同时可以获得状态。 -
getState
在子组件使用 getState 方法,可以获得状态。
使用方式
在组件里面引入js文件即可使用,很方便
// 新的列表页面的管理类
import dataListManage from '../../controller/state-list.js'
// 列表的状态管理类
const {
dataListSource, // 数据列表
getState, // 子组件获取状态
regState // 父组件注册状态
} = dataListManage(props.moduleId)
// 注册列表状态
const dataListState = regState()
其特点就是,组件里面需要写的代码特别少,就是引入js文件,获取状态,模板里面使用状态,就OK了。
网友评论