vue 自定义模块内容
📅 2026/7/17 4:40:20
👁️ 阅读次数
📝 编程学习
场景:从自己建的组件库中选择组件,选中后渲染到页面的模块中。
<template><divclass="dashbordBox"><divclass="topBox"><divclass="tLeftBox"></div><divclass="tMidBox"></div><divclass="tRightBox"></div></div><divclass="btmBox"><divclass="bLeft"><pclass="iconBox"@click="editHandle(1)"><el-iconcolor="#999"size="18"><Edit/></el-icon></p><componentv-if="moduleData[1].key && compMap[moduleData[1].key]":is="compMap[moduleData[1].key]"/></div><divclass="bRight"><divclass="rTopBox"><divclass="rwBox"><pclass="iconBox"@click="editHandle(2)"><el-iconcolor="#999"size="18"><Edit/></el-icon></p><componentv-if="moduleData[2].key && compMap[moduleData[2].key]":is="compMap[moduleData[2].key]"/></div><divclass="rcBox"><pclass="iconBox"@click="editHandle(3)"><el-iconcolor="#999"size="18"><Edit/></el-icon></p><!-- <BarChart ref="barChartsChild"></BarChart> --><componentv-if="moduleData[3].key && compMap[moduleData[3].key]":is="compMap[moduleData[3].key]"/></div></div><divclass="rBtmBox"></div></div></div><el-dialogv-model="state.comDialog"title="组件库"v-if="state.comDialog"width="90%"style="margin-top:4%"><divclass="comBox"><divclass="xxBox"@click="selectComp('msg')"><XxCom></XxCom></div><divclass="rwBox"@click="selectComp('task')"><RwCom></RwCom></div><divclass="chartBox"@click="selectComp('chart')"><BarChartref="barChartsChild"></BarChart></div><!-- <div class="zbBox"> <p>值班表值班表值班表值班表值班表值班表值班表值班表</p> </div> --></div></el-dialog></div></template><scriptsetup>import{onMounted,reactive,ref,nextTick,watch,computed}from'vue'import*asechartsfrom'echarts'importBarChartfrom'@/components/chart/barChart.vue'importXxComfrom'@/components/text/xx.vue'importRwComfrom'@/components/text/rw.vue'constbarChartsChild=ref(null)// 组件映射:key对应组件实例constcompMap={msg:XxCom,task:RwCom,chart:BarChart}// 记录当前正在操作的模块idletactiveModuleId=nullconststate=reactive({comDialog:false,})// localStorage存储key,全局唯一constSTORAGE_KEY='moduleCache'// 默认初始化数据constdefaultModuleData={1:{key:''},2:{key:''},3:{key:''},4:{key:''}}// 读取本地缓存,合并默认值letcacheStr=localStorage.getItem(STORAGE_KEY)letcacheData=nulltry{if(cacheStr){cacheData=JSON.parse(cacheStr)}}catch(err){// 缓存损坏时清空,防止页面报错localStorage.removeItem(STORAGE_KEY)cacheData=null}// 合并缓存与默认配置,保证4个模块一定存在constmoduleData=reactive({...defaultModuleData,// 兜底:保证 1/2/3/4 一定存在,key 默认空字符串...(cacheData||{})// 用本地缓存覆盖默认值,有则替换,无则保留默认})// 监听数据自动持久化watch(moduleData,(newVal)=>{localStorage.setItem(STORAGE_KEY,JSON.stringify(newVal))},{deep:true})// 打开弹窗,记录当前点击的模块编号consteditHandle=(moduleId)=>{activeModuleId=moduleId state.comDialog=true}// 弹窗选中组件,赋值给对应模块constselectComp=(compKey)=>{if(!activeModuleId)return// 给当前操作模块赋值组件moduleData[activeModuleId].key=compKey// 关闭弹窗state.comDialog=false}onMounted(()=>{barChartsChild?.value?.initChart()//只用于弹框中图表初始化展示})</script><stylelang="scss"scoped>.dashbordBox{width:100%;height:100%;.topBox{width:100%;height:20%;//padding:.5% 1%;margin-bottom:1%;display:flex;justify-content:space-between;align-items:center;//flex-wrap:wrap;.tLeftBox{width:20%;height:100%;background-color:#fff;}.tMidBox{width:60%;height:100%;background-color:#fff;}.tRightBox{width:18%;height:100%;background-color:#fff;}}.btmBox{display:flex;justify-content:space-between;align-items:center;width:100%;height:78%;.bLeft{width:28%;height:100%;background-color:#fff;}.bRight{width:71%;height:100%;//background-color:pink;.rTopBox{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.2%;width:100%;height:75%;.rwBox{width:63.5%;height:100%;background-color:#fff;}.rcBox{position:relative;width:35%;height:100%;background-color:#fff;.iconBox{position:absolute;right:0;top:0;z-index:1;}}}.rBtmBox{width:100%;height:22.5%;background-color:#fff;}}}:deep(.el-dialog__body){height:82vh;}.comBox{display:flex;flex-wrap:wrap;gap:12px;/* 模块间距,按需调整 */width:100%;height:100%;overflow:auto;.xxBox, .rwBox, .chartBox, .zbBox{width:24.4%;height:36%;background:#f5f7fa;border-radius:8px;padding:12px;overflow-y:auto;/* 内容超出时滚动 */}}}</style>组件分页面
- chart组件
<template><divref="barChart"class="barChart"></div></template><scriptsetup>import{ref,onMounted,reactive,onBeforeUnmount,nextTick}from'vue'import*asechartsfrom'echarts';constbarChart=ref(null)conststate=reactive({myChart:null})constinitChart=(res,type)=>{// 如果实例已存在,先销毁if(state.myChart){state.myChart.dispose()state.myChart=null}state.myChart=echarts.init(barChart.value)// if (state.myChart == null) {// state.myChart = echarts.init(barChart.value)// }letoption={// title: {// text: '标题',// x: "2%",// y: "3%",// left:'2%',// },tooltip:{trigger:'axis',axisPointer:{type:'shadow',},},grid:{top:'16%',left:'3%',right:'4%',bottom:'4%',containLabel:true,},xAxis:[{type:'category',data:['名称1','名称2','名称3','名称4','名称5'],axisTick:{alignWithLabel:true,},axisLabel:{// color: '#65c0ff',rotate:26,formatter:(val)=>{returnval.length>5?val.substring(0,6)+'...':val}},},],yAxis:[{type:'value',axisLabel:{// color: '#65c0ff',},axisLine:{show:true,//纵轴刻度线},splitLine:{show:true,lineStyle:{type:'dashed',color:'#ccc',},},},],series:[{name:'',type:'bar',barWidth:'36%',data:[10,52,200,334,490],itemStyle:{color:newecharts.graphic.LinearGradient(0,0,0,1,[{offset:0,color:'#5f86ff'},{offset:1,color:'#a1b8ff'}]),},},],}state.myChart.setOption(option)window.addEventListener('resize',()=>{state.myChart.resize()})}defineExpose({initChart})onMounted(()=>{nextTick(()=>{initChart()})})onBeforeUnmount(()=>{window.removeEventListener('resize',()=>{state.myChart.resize()})if(state.myChart){state.myChart.dispose()state.myChart=null}})</script><stylelang="scss"scoped>.barChart{width:100%;height:100%;//min-height:300px;}</style>2.xx组件
<template><divclass="xxContainer">消息中心 消息中心 消息中心 消息中心 消息中心 消息中心</div></template><scriptsetup>import{ref,onMounted,reactive,}from'vue'conststate=reactive({})onMounted(()=>{})</script><stylelang="scss"scoped>.xxContainer{width:100%;height:100%;}</style>- rw组件
<template> <div class="rwContainer"> 任务中心 任务中心 </div> </template> <script setup> import { ref, onMounted, reactive, } from 'vue' const state = reactive({ }) onMounted(()=>{}) </script> <style lang="scss" scoped> .rwContainer { width: 100%; height: 100%; } </style>
编程学习
技术分享
实战经验