100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > < elementUi 下拉选择框组件 树状部门选择( 多选/单选 )>

< elementUi 下拉选择框组件 树状部门选择( 多选/单选 )>

时间:2022-04-22 02:03:03

相关推荐

< elementUi 下拉选择框组件 树状部门选择( 多选/单选 )>

文章目录

前言👉 一、树状部门数据 下拉框单选实现代码:> 组件代码 ( 父 )> 组件代码 ( 子 ) 👉 二、树状部门数据 下拉框多选解释:多选和单选的代码差不多,就不做庸余的复制粘贴了。 👉 新增内容> 单选 - 新增搜索栏及树状结构懒加载(.04.21)> 具体案例代码如下:> 效果图 > 多选 - 新增二次点击已选内容,则删除该选项的选中状态,且增加已选内容分区(.07.15)> 具体案例代码如下:> 效果图 > 多选, 新增是否限制可选等级 往期内容 💨总结

前言

在前端开发中,平时在填写表单中,可能会遇到需要展示选择树状数据的表单组件。但是在element中,并未提供能够处理树状数据选择的 select 选择框组件。所以就此,小温在开发中遇到类似的问题,封装了elementUi 的select选择框组件。接下来给大家讲述一下! 希望能给大家一些帮助!

提示:以下是本篇文章正文内容,下面案例仅供参考

👉 一、树状部门数据 下拉框单选

效果图如下:

实现代码:

> 组件代码 ( 父 )

<el-form-item label="单位名称: "><SelectTreestyle="width: 100%"ref="selectTreeRef":props="defaultProps":options="treeData":value="valueId":clearable="true":accordion="true"@getValue="getValue($event)"/></el-form-item>

// 树状数据中,选定子元素名,展示名,选中值变量名defaultProps: {children: "list",label: "orgName",value: "orgId",},// 树状数据treeData: [],// 初始展开valueId: '',

> 组件代码 ( 子 )

此为 vue文件<template><el-select v-model="valueTitle" placeholder="请选择" :clearable="clearable" @clear="clearHandle"><el-option :value="valueTitle" :label="valueTitle" class="options"><el-tree id="tree-option"ref="selectTree":accordion="accordion":data="options":props="props":node-key="props.value" :default-expanded-keys="defaultExpandedKey"@node-click="handleNodeClick"></el-tree></el-option></el-select></template><script>export default {name: "el-tree-select",props:{// 配置项props:{type: Object,default: () => {return {value:'id', // ID字段名label: 'title', // 显示名称children: 'children' // 子级字段名};}},// 选项列表数据(树形结构的对象数组)options:{type: Array, default: () => {return [] } },// 初始值value:{type: String, default: () => {return null } },// 可清空选项clearable:{type:Boolean, default: () => {return true } },// 自动收起accordion:{type:Boolean, default: () => {return false } }},data() {return {valueId: null,valueTitle:'',defaultExpandedKey:[] }},mounted(){this.valueId = this.value, // 初始值this.initHandle()},methods: {// 初始化值initHandle(){if(this.valueId){setTimeout(() => {window.console.log(this.options)this.valueTitle = this.$refs.selectTree.getNode(Number(this.valueId)).data[this.props.label]// 初始化显示this.$refs.selectTree.setCurrentKey(Number(this.valueId)) // 设置默认选中this.defaultExpandedKey = [this.valueId]// 设置默认展开}, 500);} else {this.valueTitle = ""}this.initScroll()},// 初始化滚动条initScroll(){this.$nextTick(()=>{let scrollWrap = document.querySelectorAll('.el-scrollbar .el-select-dropdown__wrap')[0]let scrollBar = document.querySelectorAll('.el-scrollbar .el-scrollbar__bar')scrollWrap.style.cssText = 'margin: 0px; max-height: none; overflow: hidden;'scrollBar.forEach(ele => ele.style.width = 0)})},// 切换选项handleNodeClick(node, obj){window.console.log(obj);// if(obj.level <= 1 ) return falsethis.valueTitle = node[this.props.label]this.valueId = node[this.props.value]this.$emit('getValue', [this.valueId,this.valueTitle])this.defaultExpandedKey = []},// 清除选中clearHandle(){this.valueTitle = ''this.valueId = nullthis.defaultExpandedKey = []this.clearSelected()this.$emit('getValue', [this.valueId,this.valueTitle])},// 清空选中样式clearSelected(){let allNode = document.querySelectorAll('#tree-option .el-tree-node')allNode.forEach((element)=>element.classList.remove('is-current'))}},watch: {value(){this.valueId = this.valuethis.initHandle()}},}</script><style scoped>.el-scrollbar .el-scrollbar__view .el-select-dropdown__item{height: auto;max-height: 274px;padding: 0;overflow: hidden;overflow-y: auto;}.el-select-dropdown__item.selected{font-weight: normal;}ul li >>>.el-tree .el-tree-node__content{height:auto;padding: 0 20px;}.el-tree-node__label{font-weight: normal;}.el-tree >>>.is-current .el-tree-node__label{color: #409EFF;font-weight: 700;}.el-tree >>>.is-current .el-tree-node__children .el-tree-node__label{color:#606266;font-weight: normal;}</style>

👉 二、树状部门数据 下拉框多选

效果图如下:

解释:多选和单选的代码差不多,就不做庸余的复制粘贴了。

需要注意的就是,在父组件中,初始值 valueId 为一个数组,因为可多选的原因,返回方法接受的值也为一个数组。在赋值给 elementUi 的 select组件时,也需要将 所选内容进行处理。具体不同的,下面贴一下代码!

父组件

<SelectTreestyle="width: 100%"ref="selectTreeRef":props="defaultProps":options="treeData":value="valueId":clearable="isClearable":accordion="isAccordion"@getValue="getValue($event)"/><script>data: {defaultProps: {children: "list",label: "orgName",value: "orgId",},valueId: [],isClearable: true, // 可清空(可选)isAccordion: true, // 可回收treeData: [],},// 取值getValue(v) {if(Array.isArray(v) && v.length !== 0) {this.formData.beCheckUnitIds = v.map(item => item[this.defaultProps.value]).join(',');} else {this.formData.beCheckUnitIds = "";}},</script>

子组件

<template><el-select :value="valueTitle" :clearable="clearable" @clear="clearHandle"><el-option :value="valueTitle" :label="valueTitle" class="options"><el-treeid="tree-option"ref="selectTree":accordion="accordion":data="options":props="props":node-key="props.value":default-expanded-keys="defaultExpandedKey":filter-node-method="filterNode"@node-click="handleNodeClick"></el-tree></el-option></el-select></template><script>export default {name: "el-tree-select",props: {/* 配置项 */props: {type: Object,default: () => {return {value: "id", // ID字段名label: "title", // 显示名称children: "children", // 子级字段名};},},/* 选项列表数据(树形结构的对象数组) */options: {type: Array,default: () => {return [];},},/* 初始值 */value: {type: Array,default: () => {return [];},},/* 可清空选项 */clearable: {type: Boolean,default: () => {return true;},},/* 自动收起 */accordion: {type: Boolean,default: () => {return false;},},},data() {return {filterText: "",valueId: '', // 初始值valueTitle: "",defaultExpandedKey: [],selectData:[]};},mounted() {this.initHandle();},methods: {// 初始化值initHandle() {// window.console.log(this.$refs.selectTree)if (Array.isArray(this.value) && this.value.length !== 0) {// window.console.log(this.$refs.selectTree.getNode(10036), '***')this.value.forEach(item => {this.valueTitle += `${item[this.props.label]},`});this.selectData = JSON.parse(JSON.stringify(this.value));// this.$refs.selectTree.setCurrentKey(this.valueId); // 设置默认选中this.defaultExpandedKey = [...(this.value.map(item => item[this.props.value]))]; // 设置默认展开}this.initScroll();},// 初始化滚动条initScroll() {this.$nextTick(() => {let scrollWrap = document.querySelectorAll(".el-scrollbar .el-select-dropdown__wrap")[0];let scrollBar = document.querySelectorAll(".el-scrollbar .el-scrollbar__bar");scrollWrap.style.cssText ="margin: 0px; max-height: none; overflow: hidden;";scrollBar.forEach((ele) => (ele.style.width = 0));});},// 切换选项handleNodeClick(node) {// window.console.log(node)if (Array.isArray(node[this.props.children]) && node[this.props.children].length !== 0) {return;} else {let val ='';// window.console.log(node)if (!this.selectData.some( item => {return item[this.props.value] == node[this.props.value]})) {this.selectData.push(node)this.selectData.forEach(el=> val += `${el[this.props.label]},`);this.valueTitle = val;this.valueId = node[this.props.value];this.$emit("getValue", this.selectData);this.defaultExpandedKey = [];}}},// 清除选中clearHandle() {this.valueTitle = "";this.valueId = "";this.defaultExpandedKey = [];this.selectData = []this.clearSelected();this.$emit("getValue", null);},/* 清空选中样式 */clearSelected() {let allNode = document.querySelectorAll("#tree-option .el-tree-node");allNode.forEach((element) => element.classList.remove("is-current"));},filterNode(value, data) {if (!value) return true;return data.name.indexOf(value) !== -1;},},watch: {value() {// this.valueId = this.value;this.initHandle();},filterText(val) {this.$refs.selectTree.filter(val);},// options(val) {// window.console.log(val)// }},};</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {height: auto;max-height: 274px;padding: 0;overflow: hidden;overflow-y: auto;}.el-select-dropdown__item.selected {font-weight: normal;}ul li >>> .el-tree .el-tree-node__content {height: auto;padding: 0 20px;}.el-tree-node__label {font-weight: normal;}.el-tree >>> .is-current .el-tree-node__label {color: #409eff;font-weight: 700;}.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {color: #606266;font-weight: normal;}.selectInput {padding: 0 5px;box-sizing: border-box;}/* 开发禁用 *//* .el-tree-node:focus>.el-tree-node__content{background-color:transparent;background-color: #f5f7fa;color: #c0c4cc;cursor: not-allowed;}.el-tree-node__content:hover{background-color: #f5f7fa;} */</style>

👉 新增内容

> 单选 - 新增搜索栏及树状结构懒加载(.04.21)

💡 Tips: 本案例由于是之前写的,处在Vue2 向 Vue3 进步的学习阶段! 框架为 Vue3 ,使用的是Vue2 的语法! 有些许不一样,内容仅供参考!!

为了满足使用要求,在后端服务返回树状结构数据量多,且结构复杂时! 使用搜索框进行关键词索引,以及树状结构数据懒加载! 降低数据渲染压力,提高组件性能

> 具体案例代码如下:

父组件

<treeSeleteref="treeSelete":value="Id":treeDate="orgTreeList"placeholder="请选择机构名称"@searchTreeList="remoteMethod($event)"@changeVal="changeFormVal($event, 'params','orgId')" /><script>// 远程搜索机构async remoteMethod(query) {let {data } = await this.$axios({method: "get",url: "/center/org/listOrgTree",params: {keyword: query,t: new Date().getTime()},});TreeList = this.changeTreeData(data.data);}</script>

子组件

<template><div class="box"><!-- :key="selectValue" 如何想让el-select选中关闭,加入这个即可 --><el-select size="mini" :placeholder="placeholder" style="width: 240px;" clearable v-model="selectLabel" @clear="selectClear"><el-option class="option-style" :label="selectLabel" :value="selectValue"><el-input class="search" size="mini" placeholder="输入关键字进行过滤" v-model="keywork" @click.stop.native><template #append><el-button icon="el-icon-search" @click.stop.native="searchTree(keywork)"></el-button></template></el-input><el-treeref="tree"v-loading="loading"element-loading-text="加载中":data="treeDate":key="treeDate":props="treeProps":show-checkbox="showCheckbox":filter-node-method="filterNode"@node-click="nodeClick"@check-change="checkChange"lazy:load="loadTreeData"><!-- :expand-on-click-node="false" 是否区分点击和展示图标事件 --><template v-slot="{ node, data }"><i class="el-icon-folder-opened" style="margin-right: 5px;"></i><span :class="[{'tree-click': treeClick==data.value}]">{{data.label}}</span></template></el-tree></el-option></el-select></div></template><script>import {ElConfigProvider } from 'element-plus'export default {name: "test",components: {[ElConfigProvider.name]: ElConfigProvider},data() {return {loading: false,conciseTreeData: {},treeClick: null, //点击样式keywork: null, //搜索关键字selectLabel: null, //下拉框显示名称selectValue: null, //下拉框显示ID// treeDate: [{//label: "主-测试0",//value: 0,//children: [{// label: "子-测试0",// value: 6//}]// },// {//label: "主-测试1",//value: 1,//children: [{// label: "子-测试1",// value: 7//}]// },// {//label: "主-测试2",//value: 2,//children: [{// label: "子-测试2",// value: 8//}]// },// {//label: "主-测试3",//value: 3,//children: [{// label: "子-测试3",// value: 9//}]// },// {//label: "主-测试4",//value: 4,//children: [{// label: "子-测试4",// value: 10//}]// },// {//label: "主-测试5",//value: 5,//children: [{// label: "子-测试6",// value: 11// },// {// label: "子-测试7",// value: 12// }//]// }// ],// treeProps: {// children: "children",// label: "label"// }}},props: {treeDate: {//树状数据type: Array,default: ()=>{}},placeholder: {//当前选中type: String,default: '请选择'},value: {//当前选中type: String,default: ''},label: {//当前选中的名称type: String,default: ''},treeProps: {//树状规则type: Object,default: ()=> {return {children: "children",label: "label"};}},showCheckbox: {//是否可选择type: Boolean,default: false}},methods: {// 加载树状数据async loadTreeData(node, resolve) {// window.console.log(node, resolve)if(node.level === 0 && this.keywork) {return resolve(node.data);}let {data } = await this.$axios({method: "get",url: "/center/org/listOrgTree",params: {// keyword: this.keywork,type: 'org',id: node.data.id,isRootNode: false,t: new Date().getTime()},});// window.console.log(data)resolve(data.data.length === 1 && data.data[0].entryId === node.data.id ? [] : this.TreeData(data.data));},// 格式化树状数据TreeData(data) {let dataArr = [];data.forEach(res => {dataArr.push({id: res.entryId,label: res.text,value: res.entryId,children: res.children && res.children.length !== 0 ? this.TreeData(res.children) : []})})return dataArr;},selectClear() {this.treeClick = null;this.selectLabel = null;this.selectValue = null;},filterNode(value, data) {if (!value) {return true;}return data.label.indexOf(value) !== -1;},nodeClick(obj, node) {this.treeClick = obj.value;this.selectLabel = obj.label;this.selectValue = obj.value;console.log(obj, node);this.$forceUpdate();},checkChange(obj, node) {console.log(obj, node);},// 扁平化树状数据, 后续查询label用changeTreeData(data) {data.forEach(item => {this.conciseTreeData[item.value] = item.label;if(item.children && item.children.length !== 0) {this.changeTreeData(item.children);}})},// 搜索树状数据searchTree(queryVal) {this.loading = true;this.$emit('searchTreeList', queryVal)}},watch: {treeDate(v) {this.loading = false;this.changeTreeData(v);},keywork(val) {// this.$refs.tree.filter(val);if(val == '' || val == null || val == undefined) {this.loading = true;this.$emit('searchTreeList', '')}},selectValue(val) {this.$emit('changeVal', val)},value(v) {if(this.selectValue !== v) {this.selectValue = v;if(this.conciseTreeData[v]) {this.selectLabel = this.conciseTreeData[v];} else {this.selectLabel = this.label;}this.treeClick = v;}}},computed: {},created() {this.changeTreeData(this.treeDate);},mounted() {},beforeDestroy() {}}</script><style scoped>.box {/* width: 100%; *//* height: 100%; *//* margin: 1rem; */}.search {width: calc(100% - 8px - 0.5rem);margin: 0 0.5rem;}.option-style {padding: 0;width: 100%;height: 100%;background-color: #FFFFFF;}.tree-click {color: #4D74D6;font-weight: 600;}/deep/ .el-tree-node__content {padding: 0.25rem;}/deep/ .el-icon-caret-right {font-size: 0;}</style>

> 效果图

> 多选 - 新增二次点击已选内容,则删除该选项的选中状态,且增加已选内容分区(.07.15)

💡 Tips: 本案例由于是之前写的,处在Vue2 向 Vue3 进步的学习阶段! 框架为 Vue3 ,使用的是Vue2 的语法! 有些许不一样,内容仅供参考!!

为了满足使用要求,在使用时,难免会出现多选选错内容的情况,而且因为输入框选择内容过多时,会出现无法看见选中的内容。所以实现了标题所述效果。

> 具体案例代码如下:

父组件

<SelectTreestyle="width: 100%"ref="selectTreeRef":props="defaultProps":options="treeData":value="valueId":clearable="isClearable":accordion="isAccordion"@getValue="getValue($event)"/><script>data: {defaultProps: {children: "list",label: "orgName",value: "orgId",},valueId: [],isClearable: true, // 可清空(可选)isAccordion: true, // 可回收treeData: [],},// 取值getValue(v) {if(Array.isArray(v) && v.length !== 0) {this.formData.beCheckUnitIds = v.map(item => item[this.defaultProps.value]).join(',');} else {this.formData.beCheckUnitIds = "";}},</script>

子组件

<template><el-select :value="valueTitle" :clearable="clearable" @clear="clearHandle"><el-option-group label="已选内容"><el-option value="" label="" class="options"><el-treeid="tree-option"ref="selectTree":accordion="accordion":data="selectData":props="props":node-key="props.value":default-expanded-keys="defaultExpandedKey":filter-node-method="filterNode"@node-click="handleNodeClick"></el-tree></el-option></el-option-group><el-option-group label="选项"><el-option :value="valueTitle" :label="valueTitle" class="options"><el-treeid="tree-option"ref="selectTree":accordion="accordion":data="options":props="props":node-key="props.value":default-expanded-keys="defaultExpandedKey":filter-node-method="filterNode"@node-click="handleNodeClick"></el-tree></el-option></el-option-group></el-select></template><script>export default {name: "el-tree-select",props: {/* 配置项 */props: {type: Object,default: () => {return {value: "id", // ID字段名label: "title", // 显示名称children: "children", // 子级字段名};},},/* 选项列表数据(树形结构的对象数组) */options: {type: Array,default: () => {return [];},},/* 初始值 */value: {type: Array,default: () => {return [];},},/* 可清空选项 */clearable: {type: Boolean,default: () => {return true;},},/* 自动收起 */accordion: {type: Boolean,default: () => {return false;},},},data() {return {filterText: "",valueId: '', // 初始值valueTitle: "",defaultExpandedKey: [],selectData:[]};},mounted() {this.initHandle();},methods: {// 初始化值initHandle() {// window.console.log(this.$refs.selectTree)if (Array.isArray(this.value) && this.value.length !== 0) {// window.console.log(this.$refs.selectTree.getNode(10036), '***')this.value.forEach(item => {this.valueTitle += `${item[this.props.label]},`});this.selectData = JSON.parse(JSON.stringify(this.value));// this.$refs.selectTree.setCurrentKey(this.valueId); // 设置默认选中this.defaultExpandedKey = [...(this.value.map(item => item[this.props.value]))]; // 设置默认展开}this.initScroll();},// 初始化滚动条initScroll() {this.$nextTick(() => {let scrollWrap = document.querySelectorAll(".el-scrollbar .el-select-dropdown__wrap")[0];let scrollBar = document.querySelectorAll(".el-scrollbar .el-scrollbar__bar");scrollWrap.style.cssText ="margin: 0px; max-height: none; overflow: hidden;";scrollBar.forEach((ele) => (ele.style.width = 0));});},// 切换选项handleNodeClick(node) {// window.console.log(node)if (Array.isArray(node[this.props.children]) && node[this.props.children].length !== 0) {return;} else {let val ='';// window.console.log(node)if (!this.selectData.some( item => {return item[this.props.value] == node[this.props.value]})) {this.selectData.push(node)this.selectData.forEach(el=> val += `${el[this.props.label]},`);this.valueTitle = val;this.valueId = node[this.props.value];this.$emit("getValue", this.selectData);this.defaultExpandedKey = [];} else {// window.console.log(node, this.selectData, '再次点击已选内容,则删除');this.selectData = this.selectData.filter(item => {return node[this.props.value] !== item[this.props.value]});this.selectData.forEach(el=> val += `${el[this.props.label]},`);this.valueTitle = val;this.valueId = '';this.clearSelected();this.$emit("getValue", this.selectData);this.defaultExpandedKey = [];}}},// 清除选中clearHandle() {this.valueTitle = "";this.valueId = "";this.defaultExpandedKey = [];this.selectData = []this.clearSelected();this.$emit("getValue", null);},/* 清空选中样式 */clearSelected() {let allNode = document.querySelectorAll("#tree-option .el-tree-node");allNode.forEach((element) => element.classList.remove("is-current"));},filterNode(value, data) {if (!value) return true;return data.name.indexOf(value) !== -1;},},watch: {value() {// this.valueId = this.value;this.initHandle();},filterText(val) {this.$refs.selectTree.filter(val);},// options(val) {// window.console.log(val)// }},};</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {height: auto;max-height: 274px;padding: 0;overflow: hidden;overflow-y: auto;}.el-select-dropdown__item.selected {font-weight: normal;}ul li >>> .el-tree .el-tree-node__content {height: auto;padding: 0 20px;}.el-tree-node__label {font-weight: normal;}.el-tree >>> .is-current .el-tree-node__label {color: #409eff;font-weight: 700;}.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {color: #606266;font-weight: normal;}.selectInput {padding: 0 5px;box-sizing: border-box;}/* 开发禁用 *//* .el-tree-node:focus>.el-tree-node__content{background-color:transparent;background-color: #f5f7fa;color: #c0c4cc;cursor: not-allowed;}.el-tree-node__content:hover{background-color: #f5f7fa;} */</style>

> 效果图

> 多选, 新增是否限制可选等级

HTML改动

<!-- 父级 --><SelectTreestyle="width: 100%"ref="selectTreeRef":props="defaultProps":options="treeData":value="valueId":clearable="isClearable":accordion="isAccordion":isUseLevel="true":level="2"@getValue="getValue($event)"/><!-- 子级 --><el-option-group label="已选内容"><el-option value="" label="" class="options"><el-treeid="tree-option"ref="selectTree":accordion="accordion":data="selectData":props="props":node-key="props.value":default-expanded-keys="defaultExpandedKey":filter-node-method="filterNode"@node-click="handleNodeClick_delete"></el-tree></el-option></el-option-group>

传入参数

/* 是否使用树状等级限制,默认不启用 */isUseLevel: {type: Boolean,default: () => {return false;},},// 限制等级level: {type: Number,default: () => {return 0;},},// 删除已选选项handleNodeClick_delete(node) {let val ='';this.selectData = this.selectData.filter(item => {return node[this.props.value] !== item[this.props.value]});this.selectData.forEach(el=> val += `${el[this.props.label]},`);this.valueTitle = val;this.valueId = '';this.clearSelected();this.$emit("getValue", this.selectData);this.defaultExpandedKey = [];},handleNodeClick(node, obj) {if (this.isUseLevel? (obj.level < this.level): (Array.isArray(node[this.props.children]) && node[this.props.children].length !== 0)) {return false;} else {...未改动}},

往期内容 💨

🔥 < 了解 HTTP 这一篇就够了 :什么是 HTTP ?HTTP 和 HTTPS 有什么区别 ? >

🔥 < 每日小技巧:Vue常用修饰符 >

🔥 <Javascript技巧: Javascript 是个难泡的妞,学点技巧征服 “ 她 ” >

🔥 < 谈谈对 SPA(单页面应用)的理解 >

总结

大致内容就到这里结束啦,如果觉得有帮助的话! 希望不要吝啬手中的赞! 给小温点点赞!点个关注吧!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。