el-cascader级联选择懒加载数据回显解决办法 admin 2023-08-29 16:57:02 篇首语:本文由小编为大家整理,主要介绍了el-cascader级联选择懒加载数据回显解决办法相关的知识,希望对你有一定的参考价值。 参考技术A 亲测有效!!! :options="cascaderOptions",自己组装options是回显的关键!!! 要确认组装的数据格式是label、和value,要么就要在props设置对应关系!!! 浅谈Vue使用Cascader级联选择器数据回显中的坑这篇文章主要介绍了浅谈Vue使用Cascader级联选择器数据回显中的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 业务场景 由于项目需求,需要对相关类目进行多选,类目数据量又特别大,业务逻辑是使用懒加载方式加载各级类目数据,编辑时回显用户选择的类目。 问题描述 使用Cascader级联选择器过程中主要存在的应用问题如下: 1、由于在未渲染节点数据的情况下编辑时无法找到对应的类目数据导致无法回显,如何自动全部加载已选择类目的相关节点数据; 2、提前加载数据后,点击相应父级节点出现数据重复等; 3、使用多个数据源相同的级联选择器,产生只能成功响应一个加载子级节点数据; 4、Vue中级联选择器相应数据完成加载,依然无法回显。 解决思路 Cascader级联选择器在需要回显的节点数据都存在的情况下,方可完成回显,首先想到的是把选中节点相关的数据全部获取到即可,遍历已选择的节点数据,遍历加载相对应的数据。(如果多个级联选择器使用同一个数据源,使用深拷贝将数据分开,避免产生影响) 由于是级联的数据懒加载,需要每一级相应的节点数据加载完进行下一步,故使用ES6中的Promise,将子级节点数据加载封装成一个Promise,待Promise执行完成,对列表数据遍历获取完成后返回即可。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 getChildrenList (fid, level = 0) return new Promise((resolve, reject) => API.getCategory( fid: fid, level: level ).then( res => if (res) if (res.code === 0 && res.result) resolve(res.result) ) ) , let twolist = this.getChildrenList(codeArr[0], 1) let thirdlist = this.getChildrenList(codeArr[1], 2) Promise.all([twolist, thirdlist]).then((data) => ... ) Vue2的双向数据绑定使用ES2015中的Object.defineProperty(),该方法无法检测到Array中的深层数据变化,需要使用$set来触发列表数据的更新。 一个三级级联选择器,首先获取全部一级类目,二级类目和三级类目采用懒加载,获取数据的步骤如下: 1、获取全部一级类目; 2、由于使用异步数据加载,使用Promise进行数据请求; 3、根据已选择的类目获取相关联的二级类目和三级类目; 4、数据请求完成,使用$set触发列表数据更新,在$nextTick中完成数据你回显。 相关代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 placeholder="请选择所属类目" :options="categoryList" :show-all-levels="false" v-model="category" collapse-tags :props=" multiple: true, value: "code", label: "name", children: "children", ...props, " /> placeholder="请选择所属类目" :options="secondCategoryList" :show-all-levels="false" v-model="secondCategory" collapse-tags :props=" multiple: true, value: "code", label: "name", children: "children", ...props, " /> export default data () return categoryList: [], category: [], secondCategoryList: [], secondCategory: [], props: lazy: true, // checkStrictly: true, // 父子级节点关联 async lazyLoad (node, reso) const level, data = node if (data && data.children && data.children.length !== 0) return reso(node) if (data && data.leaf) return reso([]) const lv3Code = data ? data.code : null setTimeout(() => lv3Code && API.getCategory( fid: lv3Code, level: level ).then( res => if (res) if (res.code === 0 && res.result) const nodes = res.result.map(item => ( leaf: level === 2, ...item, children: [] )) data.children = nodes reso(nodes) else reso([]) ) , 500) , mounted () this.getCategory() this.initData() , methods: initData () let _that = this 异步获取编辑数据。。。 .then(result => // 此处仅处理result中firstCategory和secondCategory均不为空的情况 let firstTemp = _that.getCategoryListFormat(result.firstCategory, _that.categoryList) let secondTemp = _that.getCategoryListFormat(result.secondCategory, _that.secondCategoryList) let promiseArr = [firstTemp, secondTemp].filter(_ => _) Promise.all(promiseArr).then((formatRes) => // 触发列表数据响应 this.$set(_that.categoryList, formatRes[0].tragetCategoryList) this.$set(_that.secondCategoryList, formatRes[1].tragetCategoryList) _that.$nextTick(() => // 数据加载完成后,在下一次循环中回显 _that.category = formatRes[0].category _that.secondCategory = formatRes[1].category ) ) ) , getCategoryListFormat (categorySelectList, tragetCategoryList) return new Promise((resolve, reject) => const category = [] let flag = 0 let counter = categorySelectList.length categorySelectList.forEach(v => // 遍历已选择节点数据 const oneNode = v const twoNode = v.children const threeNode = v.children.children const codeArr = [oneNode.code, twoNode.code, threeNode.code] category.push(codeArr) twoNode.children = twoNode.children ? twoNode.children : [] let twolist = this.getChildrenList(codeArr[0], 1) let thirdlist = this.getChildrenList(codeArr[1], 2) Promise.all([twolist, thirdlist]).then((data) => let twochildren = data[0] let threechildren = data[1] threechildren = threechildren.map(item => ( leaf: true, ...item )) // 三级节点设置成叶子节点 twoNode.children = threechildren tragetCategoryList.forEach(w => // 遍历列表添加相应节点数据 if (w.code === oneNode.code) if (!w.children) w.children = twochildren w.children.forEach(item => if (item.code === twoNode.code) item.children = twoNode.children ) ) flag++ if (flag === counter) resolve( tragetCategoryList, category ) ) ) ) , getChildrenList (fid, level = 0) return new Promise((resolve, reject) => API.getCategory( fid: fid, level: level ).then( res => if (res) if (res.code === 0 && res.result) resolve(res.result) ) ) , getCategory(fid = 0, level = 0) API.getCategory( fid: fid, level: level ) .then( res => if (res) if (res.code == 0 && res.result) this.categoryList = this.deepClone(res.result); ) , deepClone (source) // 深拷贝 if (!source && typeof source !== "object") throw new Error("error arguments", "shallowClone") const targetObj = source.constructor === Array ? [] : Object.keys(source).forEach(keys => if (source[keys] && typeof source[keys] === "object") targetObj[keys] = source[keys].constructor === Array ? [] : targetObj[keys] = deepClone(source[keys]) else targetObj[keys] = source[keys] ) return targetObj 补充知识:Ant Design 级联选择的一种写法 简单记录类似省、市、区或品牌、车系、车型等多级结构,级联选择添加并展示的一种写法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 import React from "react"; import Button, Form, message, Row, Tag,Select,Col from "antd"; import request from "../../../../utils/request"; const FormItem = Form.Item; const Option = Select.Option; class CarSeriesCascader extends React.Component constructor(props) super(props); this.state = defaultBrandList:[], selectedCarModelList: props.carModelList ? props.carModelList : [], brandCode:null, carModelList:[], carId:null, modelCode:null, modelName:null componentDidMount() let promise = request(`/car/getBrandList`); promise.then(result => if(result != null) this.setState( defaultBrandList:result ); else message.error("获取品牌数据失败"); ).catch(err => message.error("获取品牌数据失败"); ); // this.setState( // selectedCarModelList:(this.props.carModelList ? this.props.carModelList : []) // ); this.handleChange(this.state.selectedCarModelList); getLimitList = (selectedCarModelList) => let limitList = selectedCarModelList.map((carModel,index) => let limitItem = ; limitItem.modelName = carModel.modelName; limitItem.modelCode = carModel.modelCode; limitItem.carId = carModel.carId; return limitItem; ); return limitList; addCarModel = () => let addCarModel = ; let selectedCarModelList = this.state.selectedCarModelList; // 选中车型号 if (this.state.carId !== null) // 检查车型是否已选中 for (let index = this.state.selectedCarModelList.length - 1; index >= 0; index--) let carModel = this.state.selectedCarModelList[index]; if (carModel.carId == this.state.carId) message.error("车型已在已选车型中"); return; addCarModel.carId = this.state.carId; addCarModel.modelCode = this.state.modelCode; addCarModel.modelName = this.state.modelName; selectedCarModelList.push(addCarModel); else return; this.handleChange(selectedCarModelList); this.setState( selectedCarModelList ); handleChange = (selectedCarModelList) => if (this.props.onChange) let limitList = this.getLimitList(selectedCarModelList); this.props.onChange(limitList); deleteTag = (limitCode) => debugger let selectedCarModelList = this.state.selectedCarModelList; selectedCarModelList = selectedCarModelList.filter(carModel => !(carModel.modelCode === limitCode)); this.handleChange(selectedCarModelList); this.setState(selectedCarModelList); //品牌变化 brandChange = (brandName) => this.state.defaultBrandList.map((item, index) => if (item.brandName == brandName) let promise = request(`/car/getModelList?brandCode=` + item.brandCode); promise.then(result => if(result != null) this.setState( brandCode:item.brandCode, carModelList:result ); else message.error("获取车型数据失败"); ).catch(err => message.error("获取车型数据失败:"); ); ); //车型变化 modelChange = (modelName) => this.props.form.setFieldsValue(modelName: null); let _this = this; this.state.carModelList.map((item, index) => if (item.modelName == modelName) console.log(item); this.setState( modelCode : item.modelCode, carId : item.carId, modelName : item.modelName ); ); render() const getFieldDecorator = this.props.form; //品牌名称列表 let allBrandListOption = this.state.defaultBrandList != null ? this.state.defaultBrandList.map((item, index) => return item.brandName; ) : null; //车型名称列表 let allModelListOption = this.state.carModelList != null ? this.state.carModelList.map((item, index) => return item.modelName; ) : null; const closable=true, = this.props; const existCarModel = []; const limitList = this.getLimitList(this.state.selectedCarModelList); for (let index = limitList.length - 1; index >= 0; index--) let limitItem = limitList[index]; existCarModel.push( key=limitItem.modelCode closable=closable onClose=(e) => e.preventDefault(); this.deleteTag(limitItem.modelCode); >limitItem.modelName); return ( getFieldDecorator("brandName", rules: [ message: "请选择品牌" ], )( placeholder="品牌" dropdownMatchSelectWidth=false onChange=this.brandChange style= marginRight: 10, width: 100 > null>选择品牌 allBrandListOption ) getFieldDecorator("modelName", rules: [ message: "请选择车型" ], )( placeholder="车型" dropdownMatchSelectWidth=false onChange=this.modelChange style= marginRight: 10, width: 260 > null>选择车型 allModelListOption ) "primary" icon="plus" onClick=this.addCarModel>添加车型 existCarModel ) export default Form.create()(CarSeriesCascader); 以上这篇浅谈Vue使用Cascader级联选择器数据回显中的坑就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。 开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系 以上是关于el-cascader级联选择懒加载数据回显解决办法的主要内容,如果未能解决你的问题,请参考以下文章 苹果MAC平台Citrix Receiver无法从外网访问xenapp CentOS使用sftp命令进行主机间文件传输 您可能还会对下面的文章感兴趣: 相关文章 浏览器打不开网址提示“ERR_CONNECTION_TIMED_OUT”错误代码的解决方法 如何安装ocx控件 VMware的虚拟机为啥ip地址老是自动变化 vbyone和EDP区别 linux/debian到底怎么重启和关机 苹果平板键盘被弄到上方去了,如何调回正常? 机器学习常用距离度量 如何查看kindle型号