需求介绍
突然收到领导通知需要紧急重构大屏项目,是这样的,大屏上有很多个模块,比如学校信息,教师信息,学生信息,违纪情况,考勤,打分等等,由多个模块组成。随着模块的增多,学校与学校之间产生了差异,由于不同学校需要展示的模块不同,项目需要进行重构以解决之前项目存在的兼容性问题
拿到这个需求仔细思考了一下,主要有两个难点
- 自定义模块
- 自定义布局
自定义模块:每个大屏上展示的模块,需要根据不同的方案展示不同的模块,最好是可以通过一个管理页面控制展示的模块
自定义布局:也就是自定义模块位置和大小:每个模块的大小可能随着展示模块的数量而变化,如果页面中模块展示的多那么每个模块的占用空间就小,每个模块的宽度高度随着占有的空间而改变
实现思路
首先控制整个页面的排版布局,比如模块是纵向排列还是横向排列,考虑到这两个排列方式,计划采用Flex
布局
布局方式搞定后就要在布局中插入相应模块,使用Component
动态加载组件
经过一番思考后,最后定了一套布局配置方案
{
type: "layout",
style: {
display: 'flex',
flexDirection: 'column',
flex: 1
},
children: [
{
type: "component",
url: 'Test',
name: "模块1",
style: {
flex: 1,
background: 'pink'
}
},
{
type: "layout",
style: {
display: 'flex',
flexDirection: 'row',
flex: 9
}, children: [
{
type: "layout",
style: {
display: 'flex',
flexDirection: 'column',
flex: 1
},
children: [
{
type: "component",
url: 'Test',
name: "模块2",
style: {
flex: 1,
background: 'pink'
}
}, {
type: "component",
url: 'Test',
name: "模块3",
style: {
flex: 1,
background: 'pink'
}
}
]
},
{
type: "layout",
style: {
display: 'flex',
flexDirection: 'column',
flex: 2,
},
children: [
{
type: "component",
url: 'Test',
name: "模块4",
style: {
flex: 1,
background: 'pink'
}
}, {
type: "component",
url: 'Test',
name: "模块5",
style: {
flex: 1,
background: 'pink'
}
}, {
type: "component",
url: 'Test',
name: "模块6",
style: {
flex: 1,
background: 'pink'
}
}
]
},
{
type: "layout",
style: {
display: 'flex',
flexDirection: 'column',
flex: 1
},
children: [
{
type: "component",
url: 'Test',
name: "模块7",
style: {
flex: 1,
background: 'pink'
}
},
{
type: "component",
url: 'Test',
name: "模块8",
style: {
flex: 1,
background: 'pink'
}
}
]
},
]
}
]
}
type
的值为layout
是控制布局的,style
属性控制组件是横向排列还是纵向排列,示例中模块1和下面的模块是纵向排列,模块2和3是一组,模块4,模块5,模块6是一组,模块7,模块8是一组横向排列,里面的组件都是纵向排列
type
的值为component
是渲染组件(模块)的,url
是组件的路径,name
是名称,style
控制组件的样式,主要是控制组件的大小
通过这样一套布局配置方案,已经可以满足大多数场景了
代码实现
根据上面的分析于是就封装了一个大屏模版组件
// Layout.vue
<template>
<div style="height:100%" v-if="data.type=='layout'" :style="data.style">
<Layout v-for="child in data.children" :data="child" />
</div>
<component v-else-if="data.type=='component'" :data="data" :is="data.url"></component>
</template>
<script setup lang="ts">
import { defineProps, toRefs } from 'vue';
const props = defineProps({
data: {
type: Object, // 类型
required: true, // 是否必填
default() { // 默认值
return {}
}
}
})
const { data } = toRefs(props)
</script>
<style scoped>
</style>
考虑到type
有两种情况,如果是layout
就遍历children
属性自己调用自己,向下传递child
如果类型是component
就会动态渲染组件,data
传递给相应的组件
大部分页面的布局方式都可以通过这个组件实现
总结
通过配置项灵活定制页面布局,利用大屏模板组件实现页面渲染,同时提供后台管理系统,方便修改配置项,确保功能流畅运行。希望这个方案能为大家带来启发,欢迎互相交流学习,共同进步。