当前位置: 首页 > news >正文

iview自定义下拉树菜单

最近由于项目需要,封装了第二种下拉树,带checkBox并且可以支持快速选择的下拉树。样式如下


自定义下拉树菜单.png

所实现交互功能如下:
1.点击对应的层级按钮,自动勾选出对应的所有同级节点。
2.点击自定义,清空所有勾选的节点。
3.勾选中不同层级的节点或同层级节点并没有全部选中,自动切换到自定义节点,并保存之前勾选的节点不清空。
4.在自定义中,若勾选的节点是同一个层级且此层级节点全部被选中,自动切换到对应层级按钮。

下面开始贴代码( 由于我将这种下拉树和之前普通的下拉树 是封装到同一个组件中的,所以只贴跟这次关联度较高的代码,之前的线性数组递归成树不再重复展示)

<RadioGroup v-model="radioValue" v-if="showCheckBox" @on-change="selectedRadioHandle"><Radiostyle="margin-left: 10px":label="item.value"v-for="item in radioArray":key="item.value">{{item.label}}</Radio>
</RadioGroup>
<Treeref="tree":data="suitableTreeData"@on-check-change="handleCheckedChange"check-strictlycheck-directlyshow-checkboxv-if="showCheckBox"></Tree><Button style="margin-left: 300px;" v-if="showCheckBox" @click="handleSubmit" type="primary" ghost>确定</Button><Button v-if="showCheckBox" type="primary" ghost style="margin-left: 8px" @click="cancel">取消</Button>

首先讲解tree组件上面的参数:
1.check-strictly在iview的api中是“在显示复选框的情况下,是否严格的遵循父子不互相关联的做法”,简单的说就是父子节点不关联。
2.check-directly在iview的api中是"开启后,在 show-checkbox 模式下,select 的交互也将转为 check"。
3.show-checkbox是支持多选。

接下来就是实现上面交互所需要的逻辑和代码
1.要实现第一个”点击对应的层级按钮,自动勾选出对应得所有同级节点“这个比较简单。将radioGroup里面的按钮value值根据节点层级设为对应的2,3,4,5,0。0代表自定义节点,用v-model双向绑定一个radioValue值,当点击radio按钮时将此变量作为参数传入一个找出所有同层级节点方法中。方法代码如下:

 findLevelNode(tree, nodeLevel) {//找出某层级所有节点const _this = this;// console.log("nodeLevel",nodeLevel);tree.forEach(item => {if (item.level == nodeLevel) {_this.checkedNodeArr.push(item);} else {if (item.children) {_this.findLevelNode(item.children, nodeLevel);}else { return}}});_this.checkedNodeArr = _this.checkedNodeArr.filter(item => {//这里用filter是因为递归出来的数组中会存放上一次选择的所有节点,所以过滤出当前层级的节点if (item.level == nodeLevel) {return item}});return _this.checkedNodeArr;},

2.实现第二个“点击自定义,清空所有勾选的节点”的交互也比较简单,也是用上面的方法,当选择自定义的时候,会返回一个空数组,所以不再赘述。
3.第三个需求中“勾选中不同层级的节点或同层级节点并没有全部选中,自动切换到自定义按钮,并保存之前勾选的节点不清空”。
  这个交互分为两个步骤,第一个是“勾选中不同层级的节点或同层级节点并没有全部选中,自动切换到自定义节点”。要实现这个效果,首先要获取到所勾选的节点,并判断勾选的节点是否全部属于同一个层级,如果不是切换到自定义( 获取勾选的节点可以用this.$refs.tree.getCheckedNodes()来实现 )。然后要判断当前选中层级的所有节点中有没有checked属性为false的( 这里也是用上面的findLevelNode方法来实现 )。上面两个判断我都是用ES6的every()方法来实现

let checkedArr = _this.$refs.tree.getCheckedNodes();let isChecked = checkedArr.every(item => {//选中的checkBox的层级不一致切换到自定义return item.level == _this.radioValue;});let checkArr = _this.findLevelNode( _this.suitableTreeData,_this.radioValue);let isChecked2 = checkArr.every(item => {//如果有一个同层级级节点checked为false切换到自定义return item.checked == true;});if (!isChecked || !isChecked2) {_this.radioValue = "0";_this.checkedNodesId = checkedArr.map(i => {//保存自动切换自定义时所勾选节点的idreturn i.id;});}

  由于之前设定的点击自定义按钮会清空所选节点,而要实现“切换到自定义按钮,并保存之前的勾选的节点不清空”这个逻辑,跟之前有点相冲突,所以比前两个交互难一点。这里需要在data里创建一个数组用来保存自动切换到自定义时所勾选的节点id,实现就是上面代码中checkedNodesId数组。然后在之前的getTree方法中添加一个判断

          if (_this.radioValue == "0") {//解决勾选不同层级的复选框后,切换自定义按钮时,已勾选复选框取消选中的问题_this.checkedNodesId.forEach(d => {obj.id == d ? (obj.checked = true) : obj.checked;});} else {if (obj.level == _this.radioValue) {obj.checked = true;}}

  这样在勾选不同层级或取消同层级的一个节点自动切回自定义时,也会保存上一次勾选的值。不过这样也造成了一个bug,那就时从其他radio按钮直接点回自定义按钮时,也会保存上一次的所选择的按钮,并没有清空。要解决这个bug就需在RadioGroup 的事件函数中添加一个判断,当value为0时,将checkedNodesId这个数组清空,就能解决。

4.实现“在自定义中,若勾选的节点是同一个层级且此层级节点全部被选中,自动切换到对应层级按钮。”要实现这个交互,首先也要获取所有勾选的节点( 也是用this.$refs.tree.getCheckedNodes()来实现 ),然后再将这些节点分级,我们可以将使用getCheckedNodes方法获取的节点打印出来看看

log.png

这里我分级采用的方法使用reduce将数组分级,代码如下:

groupByArray(objArr, porperty) {//根据属性值将对象数组分类return objArr.reduce((acc, obj) => {let key = obj[porperty];if (!acc[key]) {acc[key] = [];}acc[key].push(obj);return acc;}, {});}

如果对reduce不太熟悉可以去mdn上看看。然后在Tree组件的on-check-change事件方法中调用,代码如下:

handleCheckedChange() {const _this = this;let checkedArr = _this.$refs.tree.getCheckedNodes();let isChecked = checkedArr.every(item => {//选中的checkBox的层级不一致切换到自定义return item.level == _this.radioValue;});let checkArr = _this.findLevelNode( _this.suitableTreeData,_this.radioValue);let isChecked2 = checkArr.every(item => {//如果有一个同层级级节点checked为false切换到自定义return item.checked == true;});if (!isChecked || !isChecked2) {_this.radioValue = "0";_this.checkedNodesId = checkedArr.map(i => {return i.id;});}//上面是之前的对第三个交互的判断//******************************************************************************************************************let finalCheckedArr = _this.groupByArray(checkedArr, "level"); //分级后的数组let currentLevel = null; //当前勾选的层级//如果只勾选了一个层级的节点,判断这个层级的节点是否全部勾选,如果是切换到对应的业务组,如果不是切换到自定义if (Object.keys(finalCheckedArr).length < 2) {currentLevel = Object.keys(finalCheckedArr)[0];let currentLevelArr = _this.findLevelNode(_this.suitableTreeData, currentLevel).map(i => i.id);let currentCheckedLevelArr =  Object.values(finalCheckedArr)[0].map(i => i.id);//isEqual()是lodash的方法,用来判断对象或数组是否相等isEqual(currentCheckedLevelArr, currentLevelArr)? (_this.radioValue = currentLevel.toString()): _this.radioValue;}// console.log("finalCheckedArr", this.$ps(finalCheckedArr));// console.log("checkedArr", this.$ps(checkedArr));},

以上就是实现此种下拉树交互的主要代码



喜欢的朋友记得点赞、收藏、关注哦!!!

相关文章:

  • 基于STM32的温湿度光照强度仿真设计(Proteus仿真+程序设计+设计报告+讲解视频)
  • nginx 正反向代理和nginx正则
  • Tire 树(字典树/前缀树)
  • Github2025-05-04php开源项目日报 Top10
  • 【Springboot进阶】springboot+mybatis+jsqlparser实现数据权限控制
  • RAGFlow 接入企业微信应用实现原理剖析与最佳实践
  • 【聚类分析】基于copula的风光联合场景生成与缩减
  • 【QT】QT中的网络编程(TCP 和 UDP通信)
  • JAVA:使用 MapStruct 实现高效对象映射的技术指南
  • Git从入门到精通-第四章-更新仓库
  • augmentcode 竞品分析
  • 尼卡音乐 1.1.1 | 免费畅听全网音乐,支持无损下载,无广告无需注册登录
  • 多模态大语言模型arxiv论文略读(五十八)
  • docker:制作镜像+上传镜像+拉取镜像
  • 开上“Python跑的车”——自动驾驶数据可视化的落地之道
  • 精品,CentOS7.9 Yum安装Nginx,并配置JSON日志格式
  • word页眉去掉线
  • ES类迁移方法
  • 字符串问题c++
  • 以太坊智能合约开发框架:Hardhat v2 核心功能从入门到基础教程
  • 9金收官!跳水世界杯总决赛朱子锋、程子龙包揽男子10米台冠亚军
  • 11家券商一季度净利翻番:9家利润超20亿,国泰海通居首
  • 超越梅罗,这样一个亚马尔折射巴萨的容错率
  • 中国科学院院士张泽民已任重庆医科大学校长
  • “五一”假期逛上海车展请提前购票,展会现场不售当日票
  • 荆州市委书记汪元程:全市各级干部要做到慎微、慎初、慎独、慎友