【Vue】vue2移动端 ,vant2使用van-tree-select分类选择实现【全选】和【取消全选】、【搜索过滤当前children】,只影响当前显示children,并且去重


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

vant2的级联选择器组件链接传送门
在这里插入图片描述
功能需求,全选和取消全选,只做简单版。
就是两个按钮,一个全选,一个取消全选
并且只选中 || 取消 当前显示的这个children数组


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

一、页面代码

由于隐私,这里只能放静态图

在这里插入图片描述
这段代码,我封装成了一个components组件,只需要丢到popup弹出框

1. 父页面代码

<!-- 选择人员弹出框 -->
<van-popup v-model="showChose" closeable close-icon="close" position="right"
	:style="{ height: '100%', width: '100%' }">
	<!-- 弹出框内容 -->
	<ChoseUser v-if="showChose" name="参会" @onCancel="showChose = false" @onConfirm="onConfirmChose">
	</ChoseUser>
</van-popup>

2.js方法

import ChoseUser from "@/components/ChoseUser/general.vue"
export default {
	name: "vinit",
	components: {
		ChoseUser,
	},
	data() {
		return {
			showChose:false,

获取返回值

methods:{
	// 确定选中人员
	onConfirmChose(activeUser) {
		console.log(activeUser, '选中人员')
		this.showChose = false
		// 回显参会人员
		this.userOut = activeUser.map(item => item.text).join()
	},
}

二、子组件代码

1.页面

代码如下(示例):

<template>
    <div class="showUser">
        <h4 @click="getDeptList">请选择{{ name }}人员</h4>
        <van-search v-model="searchName" :placeholder="`请输入搜索的${name}人姓名`" />
        <van-loading size="24px" v-if="list.length == 0">加载中...</van-loading>
        <div class="submit">
            <van-button type="danger" plain size="small" @click="onSelectAll">全选</van-button>
            <van-button type="warning" plain size="small" @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.样式代码

代码如下(示例):

.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;
        }
    }

}

3. js代码

先看vant组件所支持的数据格式

在这里插入图片描述

它需要的是,一个对象数组,它的对象数据,就是左侧列表,children数据,就是右侧渲染的子级数据列表。
例如下列格式

testList: [
    {
        id: 1,
        text: '湖南',
        children:[{
            id:101,
            text:'长沙'
        },{
            id:102,
            text:'张家界'
        }]
    }, {
        id: 2,
        text: '广东',
        children:[{
            id:201,
            text:'深圳'
        },{
            id:202,
            text:'佛山'
        }]
    },
]

这里我的写法是,获取部门列表,然后点击部门(左侧),再请求右边人员列表
获取到人员列表后、根据当前index下标,写入到左侧对应部门的children下。代码压缩一下了。

方法大概如下,获取人员数据,按需求修改

getDeptList() {
    // 如果有传入id,则zmlk处理, 没有则通用流程处理
    let id = this.id || this.mainDept.deptId
    deptList(id).then(res => {
        let data = res.data
        data.forEach(item => {
            item.text = item.label
            item.children = []
        })
        // 添加主部门信息,可以查询全部人员
        // if (res.data.length > 1) {
        //     data.unshift({
        //         id: this.mainDept.deptId,
        //         text: this.mainDept.deptName,
        //         children: [],
        //     })
        // }
        this.list = data
    }).then(() => {
        // 获取当前用户信息所在部门,使左侧对应
        const userInfo = Cookies.get("userInfo") && JSON.parse(Cookies.get("userInfo"));
        const userDeptId = userInfo ? userInfo.deptId : null
        // 左侧选中的部门id赋值,有个人信息,赋值,没有则取第一项
        this.deptId = userDeptId || this.list[0].id

        // 设置选中部门下标为自己的部门
        let index = this.list.findIndex(item => item.id === this.deptId)
        this.activeIndex = index == -1 ? 0 : index
        this.getDeptUserList() // 调用获取部门下人员信息
    })
},
// 获取自己部门下人员列表
getDeptUserList() {
    // 如果选中部门,有人员列表,则不请求数据
    if (this.list[this.activeIndex].children.length > 0) {
        return
    }
    deptUserList(this.deptId).then(res => {
        let array = []
        res.data.filter(item => {
            array.push({
                text: item.realName,
                id: item.userName,
                deptId: item.deptId,
                userId: item.userId,
            })
        })
        // 赋值当前选中部门下children的值
        this.list[this.activeIndex].children = [...array]
        // 赋值全部人员,用于返回给父页面(对象数组)
        this.userListAll = [...this.userListAll, ...array]
    })
},

因为是一开始没有用户人员,所以我要监听器,左侧列表切换,就需要请求右边人员列表

watch: {
    // 要监听的数据,可以是数组、对象、或者普通的变量
    activeIndex: {
        // immediate: true, // 立即执行,创建页面时就执行一次
        // deep: true, // 深度监听,会监听到对象里面的属性改变
        handler(newIndex) {
            this.deptId = this.list[newIndex].id
            this.getDeptUserList()
        },
    },
},

上面代码是,获取左侧列表和右侧人员列表的方法,因为是分开获取的。
如果你的是一次性获取来的数组,那就不需要这么繁琐,虽然请求返回值变大了,可能会缓慢、

关键代码

1.子组件变量

props: {
    name: {
        type: String,
        default: "处理", // 处理||传阅, 领导||部门
    },
    // 是否多选,默认多选,
    isArray: {
        type: Boolean,
        default: true
    },
},
data() {
    return {
        activeIndex: 0, // 左侧《下标
        activeId: [], //右侧》列表选中项 ids数组
        searchName: "", // 搜索过滤
        deptId: "", // 部门id,用于查询部门人员
        list: [], // ----------------待选列表, 部门+人员子级 children嵌套
        flowList: [], // 正在处理人员,用于禁选

        userListAll: [], // 所有子级人员
        mainDept: null,// 当前用户部门信息
    }
},
created() {
    this.init()
},
mounted() {
},
methods: {
    init(){
        this.isArray ? this.activeId = [] : this.activeId = ""
        this.getDeptList() // 获取部门列表
    }
},

2. 搜索过滤器

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
        }
    }
},

3. 返回给父页面的对象数组

computed: {
    activeList() {
        let selectedData = []
        if (Array.isArray(this.activeId)) {
            console.log("计算")
            selectedData = this.activeId.map(id => {
                // 通过 id 查找对应的数据
                return this.userListAll.find(data => data.id == id);
            });
        }
        return selectedData
    },
},

4.确定和取消方法

子页面代码

// 取消
onCancel() {
    this.$emit("onCancel")
},
// 确定
onConfirm() {
    this.$emit("onConfirm", this.activeList)
},

取消方法是通过父页面去关闭
在这里插入图片描述

5.全选反选

全选反选只要变量一致,可以直接拿走使用。

// 全选
onSelectAll() {
    console.log('全选')
    const currentChildren = this.list[this.activeIndex]?.children || [];
    console.log(currentChildren)
    const selectedIdsSet = new Set(this.activeId);

    currentChildren.forEach(item => {
        selectedIdsSet.add(item.id);
    });

    this.activeId = Array.from(selectedIdsSet);
    console.log(this.activeId)
},
// 清空当前页全选
onClearAll() {
    const currentChildren = this.list[this.activeIndex]?.children || [];
    const selectedIdsSet = new Set(this.activeId);

    currentChildren.forEach(item => {
        selectedIdsSet.delete(item.id);
    });

    this.activeId = Array.from(selectedIdsSet);
},

总结

来看案例图
在这里插入图片描述

1、在部分人员列表点击全选,然后在所有人员列表页可以看到勾选中了所选人员
2、在全部人员列表全选,然后在部分人员列表取消全选。切换回全部人员,可以看到也已经取消了部分人员的选中状态。
3、过滤功能
在这里插入图片描述

修改bug

我的全选是获取当前选中项的所有children数据,但是
当我使用了search搜索过滤时,就会误伤。我在所有人员列表,搜索出来3个人,点击全选,结果选中了10个人。

现在修改

在methods下添加过滤方法

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;
    }
},

在computed中添加计算属性变量

filterUserList() {
    return this.filterNewUserList(this.list, this.searchName);
},

修改上面的全选方法
在这里插入图片描述

把list改成filterUserList就好了

清空方法不动,因为真的要清空所有,当前,清空搜索出来的人,也可以,一致修改为filterUserList

完整代码如下(白嫖需要删除部分)

<template>
    <div class="showUser">
        <h4 @click="getDeptList">请选择{{ name }}人员</h4>
        <van-search v-model="searchName" :placeholder="`请输入搜索的${name}人姓名`" />
        <van-loading size="24px" v-if="list.length == 0">加载中...</van-loading>
        <div class="submit">
            <van-button type="danger" plain size="small" @click="onSelectAll">全选</van-button>
            <van-button type="warning" plain size="small" @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 {
    deptList, // 查询部门列表 
    deptUserList, // 查询部门下的用户列表 id
} from "@/api/flow/common.js"

import {
    shouwenFormNot, // 收文未办
} from "@/api/flow/shouwen/task.js"
import {
    jobFormNot, // 任务
} from "@/api/flow/job/task.js"
import {
    sealFormNot, // 公章
} from "@/api/flow/seal/task.js"
import {
    carFormNot, // 公车
} from "@/api/flow/car/task.js"
import {
    leaveFormNot, // 请假
} from "@/api/flow/leave/task.js"

import {
    getToken
} from "@/utils/auth";
import Cookies from "js-cookie"
export default {
    name: "vinit",
    components: {

    },
    props: {
        name: {
            type: String,
            default: "处理", // 处理||传阅, 领导||部门
        },
        // 是否多选,默认多选,
        isArray: {
            type: Boolean,
            default: true
        },
        // 公文id, 有id查出正在办并禁用,没id查全部人员
        formId: {
            type: Number
        },
        // 传入部门id,6185||326, zmlk专用,没传根据自己id查当前能查询到的
        id: {
            type: String
        },
        // 选择人员类型,shouwen收文,job任务,seal公章,car公车,leave请假
        type: {
            type: String,
            default: "shouwen",
        }
    },
    data() {
        return {
            timer: null,//定时器
            activeIndex: 0, // 左侧《下标
            activeId: [], //右侧》列表选中项 ids数组
            searchName: "", // 搜索过滤
            deptId: "", // 部门id,用于查询部门人员
            list: [], // ----------------待选列表, 部门+人员子级 children嵌套
            flowList: [], // 正在处理人员,用于禁选

            userListAll: [], // 所有子级人员
            mainDept: null,// 当前用户部门信息
        }
    },
    computed: {
        activeList() {
            let selectedData = []
            if (Array.isArray(this.activeId)) {
                console.log("计算")
                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: {
        // 要监听的数据,可以是数组、对象、或者普通的变量
        activeIndex: {
            // immediate: true, // 立即执行,创建页面时就执行一次
            // deep: true, // 深度监听,会监听到对象里面的属性改变
            handler(newIndex) {
                this.deptId = this.list[newIndex].id
                this.getDeptUserList()
            },
        },
    },
    created() {
        this.mainDept = JSON.parse(Cookies.get("mainDept"))
        // 发起定时器轮询异步请求
        this.timer = setInterval(() => {
            // 执行异步请求,获取 token 的新值
            // 如果获取到了新值,则更新组件的状态
            if (typeof getToken() !== 'undefined') {
                this.init()
                // 清除定时器
                clearInterval(this.timer);
            }
        }, 30);
    },
    mounted() {
    },
    methods: {
        init() {
            this.isArray ? this.activeId = [] : this.activeId = ""
            // 公文id, 有id查出正在办并禁用,没id查全部人员
            if (this.formId) {
                switch (this.type) {
                    case "shouwen":
                        this.getShouwenList()
                        break;
                    case "job":
                        this.getJobList()
                        break;
                    case "seal":
                        this.getSealList()
                        break;
                    case "car":
                        this.getCarList()
                        break;
                    case "leave":
                        this.getLeaveList()
                        break;
                }
            } else {
                this.getDeptList() // 获取部门列表
            }
        },
        // 全选
        onSelectAll() {
            const currentChildren = this.filterUserList[this.activeIndex]?.children || [];
            console.log(currentChildren)
            const selectedIdsSet = new Set(this.activeId);

            currentChildren.forEach(item => {
                selectedIdsSet.add(item.id);
            });

            this.activeId = Array.from(selectedIdsSet);
            console.log(this.activeId)
        },
        // 清空当前页全选
        onClearAll() {
            const currentChildren = this.list[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("onConfirm", this.activeList)
        },


        // 获取部门列表
        getDeptList() {
            // 如果有传入id,则zmlk处理, 没有则通用流程处理
            let id = this.id || this.mainDept.deptId
            deptList(id).then(res => {
                let data = res.data
                // 如果传参为部门,过滤领导id
                if (this.name == "部门") {
                    data = res.data.filter(item => {
                        return item.id != 6185
                    })
                }
                data.forEach(item => {
                    item.text = item.label
                    item.children = []
                })
                // 添加主部门信息,可以查询全部人员
                if (res.data.length > 1) {
                    data.unshift({
                        id: this.mainDept.deptId,
                        text: this.mainDept.deptName,
                        children: [],
                    })
                }
                this.list = data
            }).then(() => {
                const userInfo = Cookies.get("userInfo") && JSON.parse(Cookies.get("userInfo"));
                const userDeptId = userInfo ? userInfo.deptId : null
                this.deptId = userDeptId || this.list[0].id
                console.log('当前部门id', this.deptId)
                // zmlk\通用的请求部门人员判断
                if (this.id) {
                    this.deptId = this.list[0].id // 文秘查询专用
                } else {
                    this.deptId = this.deptId // 自己的部门id
                }
                // 设置选中部门下标为自己的部门
                let index = this.list.findIndex(item => item.id === this.deptId)
                this.activeIndex = index == -1 ? 0 : index
                this.getDeptUserList()
            })
        },
        // 获取自己部门下人员列表
        getDeptUserList() {
            // 如果选中部门,有人员列表,则不请求数据
            if (this.list[this.activeIndex].children.length > 0) {
                return
            }

            deptUserList(this.deptId).then(res => {
                let array = []
                res.data.filter(item => {
                    let bool = false
                    for (const element of this.flowList) {
                        (element.userName == item.userName) && (bool = true)
                    }
                    array.push({
                        text: item.realName,
                        id: item.userName,
                        disabled: bool,
                        userName: item.userName,
                        realName: item.realName,
                        deptId: item.deptId,
                        userId: item.userId,
                    })
                })
                // 赋值当前选中部门下children的值
                this.list[this.activeIndex].children = [...array]
                // 赋值全部人员
                this.userListAll = [...this.userListAll, ...array]
            })
        },
        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;
            }
        },

        // 收文待办
        getShouwenList() {
            shouwenFormNot(this.formId).then(res => {
                this.flowList = [...res.data]
                this.getDeptList()
            })
        },
        // 任务
        getJobList() {
            jobFormNot(this.formId).then(res => {
                this.flowList = [...res.data]
                this.getDeptList()
            })
        },
        // 公章
        getSealList() {
            sealFormNot(this.formId).then(res => {
                this.flowList = [...res.data]
                this.getDeptList()
            })
        },
        // 公车
        getCarList() {
            carFormNot(this.formId).then(res => {
                this.flowList = [...res.data]
                this.getDeptList()
            })
        },
        // 请假
        getLeaveList() {
            leaveFormNot(this.formId).then(res => {
                this.flowList = [...res.data]
                this.getDeptList()
            })
        },
    },
}
</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>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个Vue2版本的移动端三级tree组件实现,支持多选、单选、全选、全不选,并且兼容vant组件库: ```vue <template> <van-tree-select v-model="checkedList" :items="items" :height="height" :max-height="maxHeight" :main-active-index.sync="mainActiveIndex" :active-id.sync="activeId" :border="false" :accordion="accordion" :selected-icon="selectedIcon" :click-nav="clickNav" @click-nav="onClickNav" > <template v-slot:content="{ item }"> <div class="tree-item"> <van-checkbox v-model="item.checked" :name="item.id" @change="onChange(item)" /> <span>{{ item.label }}</span> </div> </template> </van-tree-select> </template> <script> import { TreeSelect, Checkbox } from 'vant'; import { cloneDeep } from 'lodash'; export default { name: 'ThreeLevelTree', components: { VanTreeSelect: TreeSelect, VanCheckbox: Checkbox, }, props: { items: { type: Array, required: true, }, height: { type: [Number, String], default: 300, }, maxHeight: { type: [Number, String], default: 300, }, accordion: { type: Boolean, default: true, }, selectedIcon: { type: String, default: 'success', }, clickNav: { type: Boolean, default: false, }, defaultValue: { type: [String, Number, Array], default: null, }, defaultChecked: { type: Array, default: () => [], }, multiple: { type: Boolean, default: false, }, checkStrictly: { type: Boolean, default: false, }, }, data() { return { checkedList: cloneDeep(this.defaultChecked), mainActiveIndex: 0, activeId: this.defaultValue, }; }, watch: { defaultValue: { handler(val) { this.activeId = val; }, immediate: true, }, defaultChecked: { handler(val) { this.checkedList = cloneDeep(val); }, immediate: true, }, }, methods: { onClickNav({ index }) { this.mainActiveIndex = index; }, onChange(item) { if (!this.multiple) { this.checkedList = []; } if (item.children && !this.checkStrictly) { this.checkChildren(item, item.checked); this.checkParent(item); } else { this.checkSelf(item); this.checkParent(item); } this.$emit('change', cloneDeep(this.checkedList)); }, checkSelf(item) { const index = this.checkedList.findIndex( (v) => v.id === item.id && v.label === item.label ); if (item.checked && index === -1) { this.checkedList.push(item); } else if (!item.checked && index !== -1) { this.checkedList.splice(index, 1); } }, checkChildren(item, checked) { if (!item.children) { return; } item.children.forEach((child) => { child.checked = checked; this.checkChildren(child, checked); }); }, checkParent(item) { if (!item.parent) { return; } const parent = this.getItemById(item.parent); if (!parent) { return; } const checkedChildrenCount = parent.children.filter((child) => child.checked).length; parent.checked = checkedChildrenCount === parent.children.length; this.checkParent(parent); }, getItemById(id, items = this.items) { for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.id === id) { return item; } if (item.children) { const result = this.getItemById(id, item.children); if (result) { return result; } } } return null; }, checkAll() { this.items.forEach((item) => { item.checked = true; this.checkChildren(item, true); }); this.checkedList = cloneDeep(this.items); this.$emit('change', cloneDeep(this.checkedList)); }, uncheckAll() { this.items.forEach((item) => { item.checked = false; this.checkChildren(item, false); }); this.checkedList = []; this.$emit('change', []); }, }, }; </script> <style scoped> .tree-item { display: flex; align-items: center; } </style> ``` 上面的代码中,我们使用vantTreeSelect组件来实现Tree组件,并自定义了节点的内容区域。我们通过props属性接收组件的数据源,并通过data属性初始化组件的状态。在Tree组件中,我们实现了多选、单选、全选、全不选等功能,并通过事件和状态管理来实现这些功能。在组件的methods属性中,我们定义了一些辅助方法,用于实现复杂的业务逻辑。 为了测试这个组件,我们可以在父组件中引入这个组件,并传入测试数据和props属性: ```vue <template> <div class="container"> <three-level-tree :items="items" :default-checked="defaultChecked" :multiple="true" @change="onChange" /> <van-button @click="checkAll">全选</van-button> <van-button @click="uncheckAll">全不选</van-button> </div> </template> <script> import ThreeLevelTree from './ThreeLevelTree.vue'; export default { name: 'App', components: { ThreeLevelTree, }, data() { return { items: [ { id: 1, label: '一级节点1', children: [ { id: 11, label: '二级节点1-1', children: [ { id: 111, label: '三级节点1-1-1', }, { id: 112, label: '三级节点1-1-2', }, ], }, { id: 12, label: '二级节点1-2', children: [ { id: 121, label: '三级节点1-2-1', }, { id: 122, label: '三级节点1-2-2', }, ], }, ], }, { id: 2, label: '一级节点2', children: [ { id: 21, label: '二级节点2-1', children: [ { id: 211, label: '三级节点2-1-1', }, { id: 212, label: '三级节点2-1-2', }, ], }, { id: 22, label: '二级节点2-2', children: [ { id: 221, label: '三级节点2-2-1', }, { id: 222, label: '三级节点2-2-2', }, ], }, ], }, ], defaultChecked: [ { id: 111, label: '三级节点1-1-1', }, { id: 122, label: '三级节点1-2-2', }, ], }; }, methods: { onChange(val) { console.log('选中的节点:', val); }, checkAll() { this.$refs.tree.checkAll(); }, uncheckAll() { this.$refs.tree.uncheckAll(); }, }, }; </script> ``` 上面的代码中,我们定义了一个父组件,包含了一个三级tree组件和两个按钮。我们给三级tree组件传入了测试数据和props属性,并监听change事件输出选中的节点。在组件中,我们通过$refs获取到三级tree组件的实例,并通过调用checkAll和uncheckAll方法实现全选和全不选功能。 最后,我们将父组件渲染到页面中: ```vue <template> <div id="app"> <app /> </div> </template> <script> import App from './App.vue'; export default { components: { App, }, }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style> ``` 上面的代码中,我们将App组件渲染到页面中。至此,我们就完成了一个Vue2版本的移动端三级tree组件的实现,支持多选、单选、全选、全不选,并且兼容vant组件库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿民不加班

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值