业务场景
由于项目需求,需要对相关类目进行多选,类目数据量又特别大,业务逻辑是使用懒加载方式加载各级类目数据,编辑时回显用户选择的类目。
问题描述
使用Cascader级联选择器过程中主要存在的应用问题如下:
1、由于在未渲染节点数据的情况下编辑时无法找到对应的类目数据导致无法回显,如何自动全部加载已选择类目的相关节点数据;
2、提前加载数据后,点击相应父级节点出现数据重复等;
3、使用多个数据源相同的级联选择器,产生只能成功响应一个加载子级节点数据;
4、Vue中级联选择器相应数据完成加载,依然无法回显。
解决思路
Cascader级联选择器在需要回显的节点数据都存在的情况下,方可完成回显,首先想到的是把选中节点相关的数据全部获取到即可,遍历已选择的节点数据,遍历加载相对应的数据。(如果多个级联选择器使用同一个数据源,使用深拷贝将数据分开,避免产生影响)
由于是级联的数据懒加载,需要每一级相应的节点数据加载完进行下一步,故使用ES6中的Promise,将子级节点数据加载封装成一个Promise,待Promise执行完成,对列表数据遍历获取完成后返回即可。
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中完成数据你回显。
相关代码
<template> <div> <el-cascader placeholder="请选择所属类目" :options="categoryList" :show-all-levels="false" v-model="category" collapse-tags :props="{ multiple: true, value: 'code', label: 'name', children: 'children', ...props, }" /> <el-cascader placeholder="请选择所属类目" :options="secondCategoryList" :show-all-levels="false" v-model="secondCategory" collapse-tags :props="{ multiple: true, value: 'code', label: 'name', children: 'children', ...props, }" /> </div> </template> <script> 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 "less" scoped> </style>
补充知识:Ant Design 级联选择的一种写法
简单记录类似省、市、区或品牌、车系、车型等多级结构,级联选择添加并展示的一种写法:
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 "获取品牌数据失败"); } }).catch(err => { message.error("获取品牌数据失败"); }); // this.setState({ // selectedCarModelList:(this.props.carModelList "车型已在已选车型中"); 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"获取车型数据失败"); } }).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 "品牌" dropdownMatchSelectWidth={false} onChange={this.brandChange} style={{ marginRight: 10, width: 100 }}> <Option value={null}>选择品牌</Option> {allBrandListOption} </Select> )} {getFieldDecorator('modelName', { rules: [{ message: '请选择车型' }], })( <Select placeholder="车型" dropdownMatchSelectWidth={false} onChange={this.modelChange} style={{ marginRight: 10, width: 260 }}> <Option value={null}>选择车型</Option> {allModelListOption} </Select> )} <Button type={"primary"} icon={"plus"} onClick={this.addCarModel}>添加车型</Button> </FormItem> </Row> <Row> {existCarModel} </Row> </div> ) } } export default Form.create()(CarSeriesCascader);
以上这篇浅谈Vue使用Cascader级联选择器数据回显中的坑就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。