【Vue】vant2使用van-tree-select实现【全选、反选、搜索】,自定义组件,拿去即用。2.0版本保姆级教程

系列文章目录

这是原篇教程,本篇为升级版,旧版已废弃。对你们不友好。
【Vue】vue2移动端 ,vant2使用van-tree-select分类选择实现【全选】和【取消全选】、【搜索过滤当前children】,只影响当前显示children,并且去重


文章目录

  • 系列文章目录
  • 前言
  • 一、写在前面
  • 二、使用步骤
    • 1.html代码
    • 2.data变量
    • 3. filters过滤器
    • 4.compted计算属性
    • 5. methods方法
    • **`全选、反选、过滤、取消和确定,都不要动它。`**
    • 6.父页面用法引入
  • 解答疑惑
  • 总结


前言

由于项目又多了新功能,我发现之前写的van-tree-select全选反选组件,不友好。得改进一下。
效果如下。

van-tree-select实现全选反选组件效果实战案例


全部代码在总结,需要适当修改一点东西。就是获取列表那。不一定你的字段跟我的一样

一、写在前面

我直接把代码全部贴出来。你们其实只需要改接口方法就好了。

后面我会一步步讲解

<!--* @Author: guo-bomin 2974463764@qq.com* @Date: 2023-11-07 16:38:51* @LastEditors: guo-bomin 2974463764@qq.com* @LastEditTime: 2023-11-07 17:51:03* @FilePath: \wuzhihua-app\src\components\ChoseDept\index.vue* @Description: 郭博民16670506200* 有问题微信同号询问,急事call我* Copyright (c) 2023 by 湖南習羽科技网络有限公司, All Rights Reserved. 
--><template><div class="showUser"><h4 @click="getDeptList">请选择部门</h4><van-search v-model="searchName" :placeholder="`请输入`" /><van-loading size="24px" v-if="list.length == 0">加载中...</van-loading><div class="submit"><van-button type="info" plain size="small" @click="onSelectAll">全选</van-button><van-buttontype="warning"plainsize="small"color="#999"@click="onClearAll">取消全选</van-button></div><van-tree-select:items="list | newUserList(searchName)":active-id.sync="activeId":main-active-index.sync="activeIndex"/><div class="submit"><van-button type="default" @click="onCancel">取消</van-button><van-button type="info" @click="onConfirm">确定</van-button></div></div>
</template><script>
import { mainDepts } from "@/api/flow/common.js";export default {name: "vinit",components: {},props: {},data() {return {activeIndex: 0, // 左侧《下标activeId: [], //右侧》列表选中项 ids数组searchName: "", // 搜索过滤list: [], // ----------------待选列表, 部门+人员子级 children嵌套flowList: [], // 正在处理人员,用于禁选userListAll: [], // 所有子级项数组,用来筛选mainDept: null, // 当前用户部门信息};},computed: {// 用来返回到父页面activeList() {let selectedData = [];if (Array.isArray(this.activeId)) {selectedData = this.activeId.map((id) => {// 通过 id 查找对应的数据return this.userListAll.find((data) => data.id == id);});}return selectedData;},// 过滤后的右侧人员列表filterUserList() {return this.filterNewUserList(this.list, this.searchName);},},filters: {// 过滤选择人员newUserList(list, searchName) {let arr = [];if (searchName != "") {list.forEach((item1, index1) => {arr.push({text: item1.text,children: [],});item1.children.forEach((item2) => {if (item2.text.toLowerCase().includes(searchName.toLowerCase())) {arr[index1].children.push({id: item2.id,disabled: item2.disabled,text: item2.text,});}});});return arr;} else {return list;}},},watch: {},created() {},mounted() {this.init();},methods: {init() {this.getDeptList(); // 获取部门列表},// 全选onSelectAll() {const currentChildren =this.filterUserList[this.activeIndex]?.children || [];const selectedIdsSet = new Set(this.activeId);currentChildren.forEach((item) => {if (!item.disabled) {selectedIdsSet.add(item.id);}});this.activeId = Array.from(selectedIdsSet);},// 清空当前页全选onClearAll() {const currentChildren =this.filterUserList[this.activeIndex]?.children || [];const selectedIdsSet = new Set(this.activeId);currentChildren.forEach((item) => {selectedIdsSet.delete(item.id);});this.activeId = Array.from(selectedIdsSet);},// 取消onCancel() {this.$emit("onCancel");},// 确定onConfirm() {this.$emit("input", this.activeList);this.$emit("onConfirm", this.activeList);},// 获取部门列表getDeptList() {mainDepts().then((res) => {console.log(`res -->`, logText(res));let allData = {id: "-1",text: "全部",children: [],};let data = res.data;// 将label赋值给textdata.forEach((item) => {item.text = item.label;if (item.children) {item.children.forEach((child) => {child.text = child.label;allData.children.push(child);this.userListAll.push(child);});}});data.unshift(allData);this.list = data;});},// 搭配过滤使用filterNewUserList(list, searchName) {let arr = [];if (searchName !== "") {list.forEach((item1, index1) => {arr.push({text: item1.text,children: [],});item1.children.forEach((item2) => {if (item2.text.toLowerCase().includes(searchName.toLowerCase())) {arr[index1].children.push({id: item2.id,disabled: item2.disabled,text: item2.text,});}});});return arr;} else {return list;}},},
};
</script><style scoped lang="less">
.showUser {height: 100vh;box-sizing: border-box;padding: 30px 0;h4 {margin-bottom: 30px;padding-left: 30px;font-size: 30px;}// 选择器.van-tree-select {margin-top: 20px;height: 70% !important;.van-sidebar-item--select::before {background-color: #418af1;}.van-tree-select__item--active {color: #418af1;}}.submit {width: 100%;display: flex;justify-content: space-around;margin: 20px 0;.van-button {width: 150px;}}
}
</style>

注意,我的接口方法是对原来的返回数组进行了修改

在这里插入图片描述
在这里插入图片描述

van-tree-select是需要text、id、children

二、使用步骤

1.html代码

代码如下(示例):

<template><div class="showUser"><h4 @click="getDeptList">请选择部门</h4><van-search v-model="searchName" :placeholder="`请输入`" /><van-loading size="24px" v-if="list.length == 0">加载中...</van-loading><div class="submit"><van-button type="info" plain size="small" @click="onSelectAll">全选</van-button><van-buttontype="warning"plainsize="small"color="#999"@click="onClearAll">取消全选</van-button></div><van-tree-select:items="list | newUserList(searchName)":active-id.sync="activeId":main-active-index.sync="activeIndex"/><div class="submit"><van-button type="default" @click="onCancel">取消</van-button><van-button type="info" @click="onConfirm">确定</van-button></div></div>
</template>

2.data变量

代码如下(示例):

export default {name: "vinit",components: {},props: {},data() {return {activeIndex: 0, // 左侧《下标activeId: [], //右侧》列表选中项 ids数组searchName: "", // 搜索过滤list: [], // ----------------待选列表, 部门+人员子级 children嵌套userListAll: [], // 所有子级项数组,用来筛选};},

3. filters过滤器

由于,我有一个搜索输入框,我需要过滤的。
在这里插入图片描述
并且页面中渲染,也不能直接用list,不然起不到过滤的作用。
过滤器时传了一个参数,我不知道为啥,在filters中不能用this.searchName,反正我就写到过滤器里面了。其实拿出来,丢到methods里面效果一样。

避免methods复杂,我这里就归类到filters中了

filters: {// 过滤选择人员newUserList(list, searchName) {let arr = [];if (searchName != "") {list.forEach((item1, index1) => {arr.push({text: item1.text,children: [],});item1.children.forEach((item2) => {if (item2.text.toLowerCase().includes(searchName.toLowerCase())) {arr[index1].children.push({id: item2.id,disabled: item2.disabled,text: item2.text,});}});});return arr;} else {return list;}},
},

4.compted计算属性

  • 我需要计算,选中的人员列表,当然你会说,不是有选中项数组吗?
  • 可那个是id数组,我需要的是对象数组,我除了id,我还需要它的text值。用作回显。
  computed: {// 用来返回到父页面activeList() {let selectedData = [];if (Array.isArray(this.activeId)) {selectedData = this.activeId.map((id) => {// 通过 id 查找对应的数据return this.userListAll.find((data) => data.id == id);});}return selectedData;},// 过滤后的右侧人员列表filterUserList() {return this.filterNewUserList(this.list, this.searchName);},},

filterUserList 这个是列表中右侧的人员列表
在这里插入图片描述
它搭配了一个filterNewUserList使用,它的作用是啥呢?

过滤右侧、通过搜索。

假设右侧有10个数据,我搜索输入之后,只有5个,当我点击全选,我需要选中的是这5个,不是10个,所以它就是这个作用,但是它是个方法,为了方便,把它丢到computed里面。作为一个变量,有利于后面的全选反选方法。

5. methods方法

methods: {init() {this.getDeptList(); // 获取部门列表},// 全选onSelectAll() {const currentChildren =this.filterUserList[this.activeIndex]?.children || [];const selectedIdsSet = new Set(this.activeId);currentChildren.forEach((item) => {if (!item.disabled) {selectedIdsSet.add(item.id);}});this.activeId = Array.from(selectedIdsSet);},// 清空当前页全选onClearAll() {const currentChildren =this.filterUserList[this.activeIndex]?.children || [];const selectedIdsSet = new Set(this.activeId);currentChildren.forEach((item) => {selectedIdsSet.delete(item.id);});this.activeId = Array.from(selectedIdsSet);},// 取消onCancel() {this.$emit("onCancel");},// 确定onConfirm() {this.$emit("input", this.activeList);this.$emit("onConfirm", this.activeList);},// 获取部门列表getDeptList() {mainDepts().then((res) => {console.log(`res -->`, logText(res));let allData = {id: "-1",text: "全部",children: [],};let data = res.data;// 将label赋值给textdata.forEach((item) => {item.text = item.label;if (item.children) {item.children.forEach((child) => {child.text = child.label;allData.children.push(child);this.userListAll.push(child);});}});data.unshift(allData);this.list = data;});},// 搭配过滤使用filterNewUserList(list, searchName) {let arr = [];if (searchName !== "") {list.forEach((item1, index1) => {arr.push({text: item1.text,children: [],});item1.children.forEach((item2) => {if (item2.text.toLowerCase().includes(searchName.toLowerCase())) {arr[index1].children.push({id: item2.id,disabled: item2.disabled,text: item2.text,});}});});return arr;} else {return list;}},},

全选、反选、过滤、取消和确定,都不要动它。

6.父页面用法引入

    <!-- 选择人员弹出框 --><van-popupv-model="showChose"closeableclose-icon="close"position="right":style="{ height: '100%', width: '100%' }"><ChoseDeptv-model="activeList"@onCancel="showChose = false"@onConfirm="onConfirmChose"></ChoseDept></van-popup>

在这里插入图片描述
在这里插入图片描述

activeList就是绑定的对象数组,具体看下面疑惑解释

解答疑惑

  1. 为什么getDeptList方法里面要写一个forEach循环?
    因为我的res返回值,与vant所需要的对应不上,我的返回值label,是对应了element的tree组件,所以用text重新赋值。

  2. computed中的filterUserList可以不封装吗?
    它本质就是把一个方法的return数组,封装为变量,在全选和反选里面有用到,看起来更简洁点。

  3. userListAll的作用
    由于activeId是选中项id,我的父页面,需要的是对象数组。当我选中后,呈现的页面效果如下。
    在这里插入图片描述

  4. 取消和确定的方法里的 $emit 是啥,没见过。
    在这里插入图片描述
    左边是方法名,右边是传递的参数。
    这个是给父页面调用的,看父页面用法参数
    在这里插入图片描述

这个v-model是什么原理?
当我的子页面调用 this.$emit("input", this.activeList);
这段代码就是把值赋给input, 然后父页面只管v-model接收就好了

但是要记住,这个子页面的this.$emit("input", this.activeList); 得你自己触发调用。我的确定按钮是在子页面中的,所以我是点击了确定手动触发。

  1. 为啥我有了v-model还需要一个onConfirm方法呢?
    你需要在父页面,关闭van-popup弹窗
  2. logText方法是什么?为什么它打印出来的数组,没有显示…省略号
console.log("打印选择结果", logText(this.activeList));

由于数组或者对象打印,会显示小数点省略号
我封装了一个全局方法,专门用于打印,把它丢到main.js中就好了,随便你放哪一行

// 在main.js中定义全局方法
window.logText = function (value) {return JSON.parse(JSON.stringify(value));
};

总结

提示:这里对文章进行总结:

样式可以自由修改,我这里并没有适配的很完善。高度之类的。但是肯定,如果你也用vant组件,也是vue2项目,你可以尝试下我的这个二级选人组件。van-tree-select组件二次封装,有全选和反选。

我这里没有做主页面删除、然后子组件也跟着取消勾选。我觉得没必要、

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/134447.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

破解密码 LLM(代码LLM如何从 RNN 发展到 Transformer)

舒巴姆阿加瓦尔 一、说明 近年来&#xff0c;随着 Transformer 的引入&#xff0c;语言模型发生了显着的演变&#xff0c;它彻底改变了我们执行日常任务的方式&#xff0c;例如编写电子邮件、创建文档、搜索网络甚至编码方式。随着研究人员在代码智能任务中应用大型语言模型&am…

Docker概述

Docker概述 Docker概述Docker安装Docker命令 镜像命令容器命令操作命令 … Docker镜像容器数据卷DockerFileDocker网络管理IDEA整合DockerDocker ComposeDocker Swarm 简化版的K8s Docker为什么出现&#xff1f; 传统的项目部署&#xff0c;环境配置是十分麻烦&#xff0c;第…

如何利用JSON Schema校验JSON数据格式

最近笔者在工作中需要监控一批http接口&#xff0c;并对返回的JSON数据进行校验。正好之前在某前端大神的分享中得知这个神器的存在&#xff0c;调研一番之后应用在该项目中&#xff0c;并取得了不错的效果&#xff0c;特地在此分享给各位读者。<br style"box-sizing: …

STM32 IIC 实验

1. 可以选择I2C1&#xff0c;也可以选择I2C2&#xff0c;或者同时选择&#xff0c;同时运行 配置时钟信号 为节约空间&#xff0c;选择这两个&#xff0c;然后选择GENERATE CODE 二、HAL_I2C_Mem_Write I2C_HandleTypeDef *hi2c&#xff1a;I2C设备句柄 uint16_t DevAddress&am…

IDEA JAVA项目 导入JAR包,打JAR包 和 JAVA运行JAR命令提示没有主清单属性

一、导入JAR包 1、java项目在没有导入该jar包之前&#xff0c;如图&#xff1a;2、点击 File -> Project Structure&#xff08;快捷键 Ctrl Alt Shift s&#xff09;&#xff0c;点击Project Structure界面左侧的“Modules”如图&#xff1a;3.在 “Dependencies” 标签…

《006.Springboot+vue之旅游信息推荐系统》【有文档】

《006.Springbootvue之旅游信息推荐系统》【有文档】 项目简介 [1]本系统涉及到的技术主要如下&#xff1a; 推荐环境配置&#xff1a;DEA jdk1.8 Maven MySQL 前后端分离; 后台&#xff1a;SpringBootMybatis; 前台&#xff1a;vueElementUI; [2]功能模块展示&#xff1a; …

nodejs express uniapp 图书借阅管理系统源码

开发环境及工具&#xff1a; nodejs&#xff0c;mysql5.7&#xff0c;HBuilder X&#xff0c;vscode&#xff08;webstorm&#xff09; 技术说明&#xff1a; nodejs express vue elementui uniapp 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示轮播图&am…

为全志T507-H开发板配置Samba服务,高效实现跨系统的文件共享

作为一款经典的国产芯&#xff0c;全志T507-H芯片被广泛应用于车载电子、电力、医疗、工业控制、物联网、智能终端等诸多领域当中&#xff0c;而在各种复杂的嵌入式Linux应用场景当中&#xff0c;“打通ARM板卡与Windows设备间的壁垒以实现跨平台的文件共享”是一项不能被忽视的…

电脑风扇控制软件 Macs Fan Control Pro mac中文版功能介绍

Macs Fan Control mac是一款专门为 Mac 用户设计的软件&#xff0c;它可以帮助用户控制和监控 Mac 设备的风扇速度和温度。这款软件允许用户手动调整风扇速度&#xff0c;以提高设备的散热效果&#xff0c;减少过热造成的风险。 Macs Fan Control 可以在菜单栏上显示当前系统温…

(三)Spring源码解析:自定义标签解析

一、使用示例 步骤1&#xff1a;创建User实体 步骤2&#xff1a;定义一个XSD文件描述组件内容 步骤3&#xff1a;创建BeanDefinitionParser接口的实现类&#xff0c;用来解析XSD文件中的定义和组件定义。 步骤4&#xff1a;创建NamespaceHandlerSupport实现类&#xff0c;目的…

多门店自助点餐+外卖二合一小程序源码系统 带完整搭建教程

随着餐饮业的快速发展和互联网技术的不断进步&#xff0c;越来越多的餐厅开始采用自助点餐和外卖服务。市场上许多的外卖小程序APP应运而生。下面罗峰来给大家介绍一款多门店自助点餐外卖二合一小程序源码系统。该系统结合了自助点餐和外卖服务的优势&#xff0c;为餐厅提供了一…

Redis极速上手开发手册【Redis全面复习】

文章目录 什么是RedisRedis的特点Redis的应用场景Redis安装部署Redis基础命令Redis多数据库特性Redis数据类型Redis数据类型之stringRedis数据类型之hashRedis数据类型之listRedis数据类型之setRedis数据类型之sorted set案例&#xff1a;存储高一班的学员信息 Redis封装工具类…

解决Java中https请求接口报错问题

1. 解决SSLException: Certificate for &#xff1c;域名&#xff1e; doesn‘t match any of the subject alternative报错问题 1.1 问题描述 最近在做一个智能问答客服项目&#xff0c;对接的是云问接口&#xff0c;然后云问接口对接使用的是https方式&#xff0c;之前一直…

「随笔」浅谈2023年云计算的发展趋势

在2023年&#xff0c;云计算的发展趋势将受到政治、经济、社会和科技四个维度的影响。以下是对这些维度的具体分析&#xff1a; 1.1 政治维度&#xff1a; 全球政策推动&#xff1a; 随着全球各国政策对云计算的重视程度不断提高&#xff0c;云计算服务将获得更广泛的市场准入…

浅谈指针函数、函数指针、指针数组、数组指针 简单明了!!!!

指针函数 形如&#xff1a;int* fun(int a, int b) 类比于&#xff1a;int fun(int x, int y)、char fun(int x, int y) 本质上是函数&#xff0c;只是返回值为int类型的指针&#xff0c;以此类推可以有void*、char*、unsigned char*类型等指针&#xff0c;类比于返回值是int …

产品经理墨刀学习----注册页面

我们做的产品是一个校园论坛学习开发系统&#xff0c;目前才开始学习。 &#xff08;一&#xff09;流程图 &#xff08;二&#xff09;简单墨刀设计--注册页面 &#xff08;1&#xff09;有账号 &#xff08;a&#xff09;直接登录&#xff1a; &#xff08;b&#xff09;忘…

什么是Target Plus EDI?

“Target Plus” 是美国知名零售商Target&#xff08;塔吉特&#xff09;推出的一个合作伙伴计划。这个计划允许第三方卖家在Target.com&#xff08;塔吉特官方网站&#xff09;上销售他们的商品。通过Target Plus&#xff0c;第三方卖家可以将他们的产品列在Target.com上&…

ZKP8.2 FRI (Univariate) Polynomial Commitment

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 8: FRI-based Polynomial Commitments and Fiat-Shamir (Justin Thaler) 8.2 FRI (Univariate) Polynomial Commitment Recall: Univariate Polynomial Commitments Initial Attempt from Lecture 4 (Merkle Tree) Fixing…

【LearnOpenGL基础入门——2】搭建第一个OpenGL窗口

目录 一.配置GLFW 二.配置GLAD 三.第一个OpenGL窗口 3.1 GLFW设置 3.2 GLAD设置 3.3 视口 3.4 输入 3.5渲染 在我们画出出色的效果之前&#xff0c;首先要做的就是创建一个OpenGL上下文(Context)和一个用于显示的窗口。然而&#xff0c;这些操作在每个系统上都是不一样…

远程调用,参数压缩问题

错误信息 { "msg": "Error while extracting response for type [XXX] and content type [application/json;charsetUTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal charac…