vue3,后台管理列表页⾯各组件之间的状态关系
技术栈
vite2
vue 3.0.5
vue-router 4.0.6
vue-data-state 0.1.1
element-plus 1.0.2-beta.39
前情回顾
前⾯介绍的表单控件和查询控件,都是原⼦性的,实现⾃⼰的功能即可。
⽽这⾥要介绍的是管理后台⾥⾯的各个组件之间的状态关系。
为啥需要状态?因为组件划分的⾮常原⼦化(细腻),所以造成了很多的组件,那么组件之间就需要⼀种“通讯⽅式”,这个就是状态了。不仅仅是传递数据,还可以实现事件总线。
页⾯结构
⼀般的后台管理⼤体是这样的结构:
具体项⽬⾥页⾯结构会有⼀些变化,但是总体结构不会有太⼤的改变。
做出来的效果⼤体是这样的:
动态菜单
根据⽤户权限加载需要的菜单。
动态 tab
点击⼀下左⾯的菜单,创建⼀个新的tab,然后加载对应的组件,⼀般是列表页⾯(组件),也可以是其他页⾯(组件)。
查询
各种查询条件那是必备的,总不能没有查询功能吧,查询控件需要提供查询条件。
操作按钮组
⾥⾯可以有常见的添加、修改、删除、查看按钮,也可以有⾃定义的其他按钮。可以“弹窗”也可以直接调⽤后端API。
列表
显⽰客户需要的数据,看起来简单,但是要和查询、翻页、添加、修改、删除等功能配合。
分页
这是和列表最接近的⼀个需求,因为数据有可能很⼤,不能⼀次性都显⽰出来,那么就需要分页处理,所以分页控件和列表控件就是天然CP。
表单(添加、修改)
数据提交之后,为了便于确认数据添加成功,是不是需要通知列表去更新数据呢?总不能填完数据,列表⼀点变化都没有吧。
删除
数据删掉了,不管是物理删除还是逻辑删除,列表⾥⾯都不需要再显⽰出来了。
也就是说删除后要通知列表更新数据。
总之,各个组件直接需要统筹⼀下状态关系。
视频演⽰
我们来看⼀下实际效果。
【放视频】
设计状态
我们整理⼀下需求,⽤脑图表达出来:
使⽤“轻量级状态管理”定义状态:/store-ds/index.js
import VuexDataState from 'vue-data-state'
export ateStore({
global: { // 全局状态
userOnline: {
name: 'jyk' //
}
},
local: { // 局部状态
dataListState () { // 获取列表数据的状态 dataPagerState
return {
query: {}, // 查询条件
pager: { // 分页参数
pageTotal: 100, // 0:需要统计总数;其他:不需要统计总数
pageSize: 5, // ⼀页记录数
pageIndex: 1, // 第⼏页的数据,从 1  开始
orderBy: { id: false } // 排序字段
},
choice: { // 列表⾥⾯选择的记录
dataId: '', // 单选,便于修改和删除
dataIds: [], // 多选,便于批量删除
row: {}, // 选择的记录数据,仅限于列表⾥⾯的。
rows: [] // 选择的记录数据,仅限于列表⾥⾯的。
},
hotkey: () => {}, // 处理快捷键的事件,⽤于操作按钮
reloadFirstPager: () => {}, // 重新加载第⼀页,统计总数(添加后)
reloadCurrentPager: () => {}, // 重新加载当前页,不统计总数(修改后)
reloadPager: () => {} // 重新加载当前页,统计总数(删除后)
}
}
},
init (state) {
}
})
这⾥没有使⽤ Vuex,因为我觉得 Vuex 有点臃肿,还是⾃⼰做的清爽。
另外,状态⾥⾯除了数据之外,还可以有⽅法(事件总线)。
组件⾥⾯使⽤轻量级状态的⽅法
// 引⼊状态
import VueDS from 'vue-data-state'
/
/ 访问状态
const { reg, get } = VueDS.useStore()
// ⽗组件注册列表的状态
const state = reg.dataListState()
// ⼦组件⾥⾯获取⽗组件注册的状态
const dataListState = get.dataListState()
先引⼊状态,然后在⽗组件注册(也就是注⼊)状态,然后在⼦组件就可以获取状态。函数名就是 /store-ds/index.js ⾥⾯定义的名称。
然后我们还可以仿照 MVC 的 Controllar ,做⼀个控制类,当然也可以叫做管理类。
叫什么不是重点,重点是实现了什么功能。
列表的管理类
我们可以为列表的状态写⼀个状态的管理类。
这个类是在单独的 js ⽂件⾥⾯,并不需要像 Vuex 那样去设置 action 或者 module。
/control/data-list.js
import { watch, reactive } from 'vue'
// 状态
import VueDS from 'vue-data-state'
// 仿后端API
import service from '../api/dataList-service.js'
/**
* * 数据列表的通⽤管理类
* * 注册列表的状态
* * 关联获取数据的⽅式
* * 设置快捷键
* @param {string} modeluId 模块ID
* @returns 列表状态管理类
*/
export default function dataListControl (modeluId) {
// 显⽰数据列表的数组
const dataList = reactive([])
// 模拟后端API
js获取json的key和valueconst { loadDataList } = service()
// 访问状态
const { reg, get } = VueDS.useStore()
/
/ ⼦组件⾥⾯获取⽗组件注册的状态
const dataListState = get.dataListState()
// 数据加载中
let isLoading = false
/**
* ⽗组件注册状态
* @returns 注册列表状态
*/
const regDataListState = () => {
// 注册列表的状态,⽤于分页、查询、添加、修改、删除等
const state = reg.dataListState()
/
/  重新加载第⼀页,统计总数(添加、查询后)
isLoading = true
state.pager.pageIndex = 1 // 显⽰第⼀页
// 获取数据
loadDataList(modeluId, state.pager, state.query, true).then((data) => {
state.pager.pageTotal = unt
dataList.length = 0
dataList.push(...data.list)
isLoading = false
})
}
// 先执⾏⼀下,获取初始数据
// 重新加载当前页,不统计总数(修改后)
// 获取数据
loadDataList(modeluId, state.pager, state.query).then((data) => {
dataList.length = 0
dataList.push(...data)
})
}
/
/ 重新加载当前页,统计总数(删除后)
// 获取数据
loadDataList(modeluId, state.pager, state.query, true).then((data) => {
state.pager.pageTotal = unt
dataList.length = 0
dataList.push(...data.list)
})
}
// 监听,⽤于翻页控件的翻页。翻页,获取指定页号的数据
watch(() => state.pager.pageIndex, () => {
/
/ 避免重复加载
if (isLoading) {
// 不获取数据
return
}
// 获取数据
loadDataList(modeluId, state.pager, state.query).then((data) => {
dataList.length = 0
dataList.push(...data)
})
})
return state
}
return {
setHotkey, // 设置快捷键,(后⾯介绍)
regDataListState, // ⽗组件注册状态
dataList, // ⽗组件获得列表
dataListState // ⼦组件获得状态
}
}
管理类的功能:
1. ⽗组件注册状态
2. ⼦组件获取状态
3. 定义列表数据的容器
4. 各种监听
5. 事件总线
⽗组件注册状态
因为使⽤的是局部的状态,并不是全局状态,所以在需要使⽤的时候,⾸先需要在⽗组件⾥⾯注册⼀下。看起来似乎没有全局状态简单,但是可以更好的实现复⽤,更轻松的区分数据,兄弟组件的状态不会混淆。
⼦组件获取状态
因为或者状态必须在vue的直接函数内才⾏,所以才需要先把状态获取出来,⽽不能等到触发事件了再获取。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。