vue-element-admin左边树形,右边格子的布局。vue element ui模板。树形tree 动态自适应屏幕高度 电脑版发表于:2021/12/23 17:19 [TOC] ### 效果如下: ![](https://img.tnblog.net/arcimg/aojiancc2/f05f83dd83ba4f59a68677280ba48a23.png) ### 代码如下: ``` <template> <div class="app-container student-archives"> <div style="display: flex"> <el-card class="box-card" style="width: 300px; margin-right: 10px"> <!-- <div slot="header" class="clearfix"><span> </span></div> --> <el-scrollbar style="height: 640px"> <el-tree ref="tree" :data="treeData" node-key="id" :expand-on-click-node="false" highlight-current @node-click="nodeClick" ></el-tree> </el-scrollbar> </el-card> <el-card class="box-card" style="flex: 1"> <div class="clearfix"> <div style="flex: 1" /> <el-input placeholder="请输入档案" /> <el-button type="primary">搜索</el-button> </div> <el-row :gutter="20" style="margin-top: 10px"> <el-col v-for="(item, index) in iconList" :key="index" :lg="3" :md="3" :sm="6" :xl="3" :xs="12" > <vab-card class="icon-panel" shadow="hover"> <vab-icon :icon="item.icon" :style="{ color: item.color }" /> <p>我是档案</p> </vab-card> </el-col> <!-- <vab-draggable v-model="iconList" v-bind="dragOptions" item-key="icon" style="position: relative; display: flex; flex-wrap: wrap" > <template #item="{ element: item }"> <el-col :lg="3" :md="3" :sm="6" :xl="3" :xs="12"> <vab-card class="icon-panel" shadow="hover"> <vab-icon :icon="item.icon" :style="{ color: item.color }" /> <p>按住拖拽</p> </vab-card> </el-col> </template> </vab-draggable> --> </el-row> </el-card> </div> </div> </template> <script> import { getIconList } from '@/api/remixIcon' export default { // 组件名字 name: 'ArchivesManager', data() { return { courseID: '', labId: '', iconList: [], treeData: [ { label: '人事档案', children: [ { label: '初始档案', children: [ { label: '2019', }, { label: '2020', }, { label: '2021', }, ], }, { label: '简化档案', children: [ { label: '简化一版', }, { label: '简化二版', }, { label: '简化三版', }, ], }, ], }, { label: '合同档案', children: [ { label: '二级 2-1', children: [ { label: '三级 2-1-1', }, ], }, { label: '二级 2-2', children: [ { label: '三级 2-2-1', }, ], }, ], }, { label: '会计档案', children: [ { label: '二级 3-1', children: [ { label: '三级 3-1-1', }, ], }, { label: '二级 3-2', children: [ { label: '三级 3-2-1', }, ], }, ], }, ], } }, mounted() { this.initPic() }, // 组件方法 methods: { // randomHexColor() { // return _.shuffle([ // '#1890FF', // '#36CBCB', // '#4ECB73', // '#FBD437', // '#F2637B', // '#975FE5', // ]) // }, randomHexColor() { return '#1890FF' }, dragOptions() { return { animation: 600, group: 'description', disabled: false, ghostClass: 'ghost', } }, initPic() { //测试数据 const list = [ '24-hours-fill', '24-hours-line', '4k-fill', '4k-line', 'a-b', 'account-box-fill', 'account-box-line', 'account-circle-fill', 'account-circle-line', 'account-pin-box-fill', 'account-pin-box-line', 'account-pin-circle-fill', 'account-pin-circle-line', 'add-box-fill', 'add-box-line', ] let my = this this.iconList = list //.filter((icon) => icon.includes('-line')) .map((icon, index) => { return { icon, color: my.randomHexColor(), order: index + 1 } }) console.log(this.iconList) }, }, } </script> <style scoped="scoped"> .custom-tree-node { display: flex; flex: 1; align-items: center; justify-content: space-between; padding-right: 8px; font-size: 14px; } .el-input { width: 200px; margin-right: 10px; } .clearfix { display: flex; } </style> <style lang="scss"> .student-archives { .el-scrollbar__wrap { overflow-x: hidden; } .el-tree-node__content { height: 40px; } } .vab-app-main { padding: 0px !important; } </style> ``` 右边的宽度比例可以自己调,上面的效果是写的自适应的,看官网的element ui文档就知道了,element ui布局是分的24份,响应式布局有五个响应尺寸:xs、sm、md、lg 和 xl,我这里是适配的lg的3分,也就是3/24,也就是1/8,也就是一行占8份 ``` <el-col v-for="(item, index) in iconList" :key="index" :lg="3" :md="3" :sm="6" :xl="3" :xs="12" > ``` 如果我们不要自适应布局,就想保持一行放2块的话,一块就是占用24份的一半就是12份就行了,设置:span="12"。el-row的gutter属性是用来设置间隔的,比如这里的:gutter="20"就是两个块之间间隔20个像素 ``` <el-row :gutter="20" style="margin-top: 10px"> <el-col v-for="(item, index) in iconList" :key="index" :span="12"> <vab-card class="icon-panel" shadow="hover"> <vab-icon :icon="item.icon" :style="{ color: item.color }" /> <p>我是档案</p> </vab-card> </el-col> </el-row> ``` 官方的布局文档:https://element.eleme.io/#/zh-CN/component/layout ### vue3中得写法 ``` <template> <div class="app-container student-archives"> <div style="display: flex"> <el-card class="box-card" style="width: 300px; margin-right: 10px"> <!-- <div slot="header" class="clearfix"><span> </span></div> --> <el-scrollbar style="height: 640px"> <el-tree ref="tree" :data="treeData" node-key="id" default-expand-all :expand-on-click-node="false" highlight-current @node-click="nodeClick" ></el-tree> </el-scrollbar> </el-card> <el-card class="box-card" style="flex: 1"> <div class="clearfix"> <div style="flex: 1" /> <el-input placeholder="请输入档案" /> <el-button type="primary">搜索</el-button> </div> <el-row :gutter="20" style="margin-top: 10px"> <el-col v-for="(item, index) in iconList" :key="index" :lg="12" :md="12" :xl="8" > <vab-card class="icon-panel" shadow="hover"> <vab-icon :icon="item.icon" :style="{ color: item.color }" /> <p>我是档案</p> </vab-card> </el-col> <!-- <vab-draggable v-model="iconList" v-bind="dragOptions" item-key="icon" style="position: relative; display: flex; flex-wrap: wrap" > <template #item="{ element: item }"> <el-col :lg="3" :md="3" :sm="6" :xl="3" :xs="12"> <vab-card class="icon-panel" shadow="hover"> <vab-icon :icon="item.icon" :style="{ color: item.color }" /> <p>按住拖拽</p> </vab-card> </el-col> </template> </vab-draggable> --> </el-row> </el-card> </div> </div> </template> <script> import { doEdit, getArchivesTypeGroup } from '@/api/archivesType' export default defineComponent({ name: 'ArchivesManager', setup(props, { emit }) { const $baseMessage = inject('$baseMessage') const state = reactive({ iconList: [], treeData: [ { label: '人事档案', children: [ { label: '初始档案', children: [ { label: '2019', }, { label: '2020', }, { label: '2021', }, ], }, { label: '简化档案', children: [ { label: '简化一版', }, { label: '简化二版', }, { label: '简化三版', }, ], }, ], }, { label: '合同档案', children: [ { label: '二级 2-1', children: [ { label: '三级 2-1-1', }, ], }, { label: '二级 2-2', children: [ { label: '三级 2-2-1', }, ], }, ], }, { label: '会计档案', children: [ { label: '二级 3-1', children: [ { label: '三级 3-1-1', }, ], }, { label: '二级 3-2', children: [ { label: '三级 3-2-1', }, ], }, ], }, ], }) const randomHexColor = async () => { return '#1890FF' } const fetchData = async () => { // const { // data: { list }, // } = await getArchivesTypeGroup() // state.treeData = list } const getArchives = async () => { //测试数据 const list = [ '24-hours-fill', '24-hours-line', '4k-fill', '4k-line', 'a-b', 'account-box-fill', 'account-box-line', 'account-circle-fill', 'account-circle-line', 'account-pin-box-fill', 'account-pin-box-line', 'account-pin-circle-fill', 'account-pin-circle-line', 'add-box-fill', 'add-box-line', ] state.iconList = list //.filter((icon) => icon.includes('-line')) .map((icon, index) => { return { icon, color: randomHexColor(), order: index + 1 } }) } onMounted(() => { fetchData() getArchives() }) return { ...toRefs(state), } }, }) </script> <style scoped="scoped"> .custom-tree-node { display: flex; flex: 1; align-items: center; justify-content: space-between; padding-right: 8px; font-size: 14px; } .el-input { width: 200px; margin-right: 10px; } .clearfix { display: flex; } </style> <style lang="scss"> .student-archives { .el-scrollbar__wrap { overflow-x: hidden; } .el-tree-node__content { height: 40px; } } .vab-app-main { padding: 0px !important; } </style> ``` ### vue3版本看这个,上面那个好像直接复制进去有点问题了 ``` <template> <div class="course-module-settings-container student-archives"> <div style="display: flex"> <el-card class="box-card" style="width: 300px; margin-right: 10px"> <el-scrollbar style="height: 640px"> <el-tree ref="tree" :data="state.treeData" node-key="id" :expand-on-click-node="false" highlight-current></el-tree> </el-scrollbar> </el-card> <el-card class="box-card" style="flex: 1"> <div class="clearfix"> <div style="flex: 1" /> <el-input placeholder="请输入档案" /> <el-button type="primary">搜索</el-button> </div> <el-row :gutter="20" style="margin-top: 10px"> <el-col v-for="(item, index) in state.iconList" :key="index" :lg="3" :md="3" :sm="6" :xl="3" :xs="12"> <vab-card class="icon-panel" shadow="hover"> <vab-icon :icon="item.icon" :style="{ color: item.color }" /> <p>我是档案</p> </vab-card> </el-col> </el-row> </el-card> </div> </div> </template> <script setup lang="ts" name="courseModuleSettings"> import { defineAsyncComponent, reactive, onMounted, toRefs, ref } from 'vue'; const state = reactive({ title: '更新', iconList: [], treeData: [ { label: '人事档案', children: [ { label: '初始档案', children: [ { label: '2019', }, { label: '2020', }, { label: '2021', }, ], }, { label: '简化档案', children: [ { label: '简化一版', }, { label: '简化二版', }, { label: '简化三版', }, ], }, ], }, { label: '合同档案', children: [ { label: '二级 2-1', children: [ { label: '三级 2-1-1', }, ], }, { label: '二级 2-2', children: [ { label: '三级 2-2-1', }, ], }, ], }, { label: '会计档案', children: [ { label: '二级 3-1', children: [ { label: '三级 3-1-1', }, ], }, { label: '二级 3-2', children: [ { label: '三级 3-2-1', }, ], }, ], }, ], }); onMounted(() => {}); </script> <style scoped="scoped" lang="scss"> .course-module-settings-container { padding: 15px; .el-input { width: 200px; margin-right: 10px; } .clearfix { display: flex; } } </style> <style lang="scss"> .student-archives { .el-scrollbar__wrap { overflow-x: hidden; } .el-tree-node__content { height: 40px; } } </style> ``` ### vue3版本加上了一点动态自适应屏幕高度的 ``` <template> <div class="course-module-settings-container student-archives"> <div style="display: flex"> <el-card class="box-card" style="width: 300px; margin-right: 10px"> <el-scrollbar :style="{height:state.contentHeight}"> <el-tree ref="tree" :data="state.treeData" node-key="id" :expand-on-click-node="false" highlight-current></el-tree> </el-scrollbar> </el-card> <el-card class="box-card" style="flex: 1"> <div class="clearfix"> <div style="flex: 1" /> <el-input placeholder="请输入档案" size="default" /> <el-button type="primary" size="default">搜索</el-button> </div> <div> 其他内容... </div> </el-card> </div> </div> </template> <script setup lang="ts" name="courseModuleSettings"> import { defineAsyncComponent, reactive, onMounted, toRefs, ref } from 'vue'; const state = reactive({ title: '更新', iconList: [], contentHeight:"150px", treeData: [ { label: '人事档案', children: [ { label: '初始档案', children: [ { label: '2019', }, { label: '2020', }, { label: '2021', }, ], }, { label: '简化档案', children: [ { label: '简化一版', }, { label: '简化二版', }, { label: '简化三版', }, ], }, ], }, { label: '合同档案', children: [ { label: '二级 2-1', children: [ { label: '三级 2-1-1', }, ], }, { label: '二级 2-2', children: [ { label: '三级 2-2-1', }, ], }, ], }, { label: '会计档案', children: [ { label: '二级 3-1', children: [ { label: '三级 3-1-1', }, ], }, { label: '二级 3-2', children: [ { label: '三级 3-2-1', }, ], }, ], }, ], }); onMounted(() => { autoHeight() // 让f12全屏的时候或者退出全屏的时候可以让高度跟着自适应变化 window.addEventListener('resize', autoHeight); }); const autoHeight = ()=>{ // 动态调整高度 state.contentHeight = window.innerHeight-(53+15+85)+"px" } </script> <style scoped="scoped" lang="scss"> .course-module-settings-container { padding: 15px; .el-input { width: 200px; margin-right: 10px; } .clearfix { display: flex; } } </style> ```