【Vue】vue/树形结构利用递归组件生成无限极联动按钮组件DEMO

 

 

 

使用方法:

组件属性

:data =>  [Array] 需要的数据格式(数据库id,pid那种,见示例代码)

:activies => [Array] 当前全部的选中值

组件事件

@click => 点击事件

<bch-nav :data="list" @click="navItemClick" :activies="activies"></bch-nav>

使用示例代码:

        new Vue({
            name: 'app',
            template: `
                <bch-nav :data="list" @click="navItemClick" :activies="activies"></bch-nav>
                `,
            components: { bchNav },
            data() {
                return {
                    list: [
                        { id: 1, name: "广东", pid: 0 },
                        { id: 2, name: "广州", pid: 1 },
                        { id: 3, name: "深圳", pid: 1 },
                        { id: 4, name: "龙岗", pid: 3 },
                        { id: 5, name: "福田", pid: 3 },
                        { id: 6, name: "宝龙", pid: 4 },
                        { id: 7, name: "山西", pid: 0 },
                        { id: 8, name: "太原", pid: 7 },
                        { id: 9, name: "临汾", pid: 7 },

                    ],
                    activies: []
                }
            },
            methods: {
                navItemClick(item) {
                    console.log(item);
                }
            }
        }).$mount('#div')

 

样式源码:

    <style>
        #app {
            position: relative;
        }

        .button {
            width: 100px;
            padding: 4px 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            text-align: center;
        }

        .button:hover {
            cursor: default;
        }

        .item-box {
            position: absolute;
            top: 180px;
        }

        .button.active {
            background-color: #666;
            color: #fff;
        }
    </style>

模板代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>
    <div id="div"></div>
</body>

</html>

JS代码:

        const bchNav = {
            name: 'bch-nav',
            props: {
                data: {
                    type: Array,
                    default: () => {
                        return []
                    }
                },
                activies: {
                    type: Array,
                    default: () => {
                        return []
                    }
                }
            },
            template: `
            <div>
                <h2>{{activies}}</h2>
                <bch-nav-item :list="list" @click="itemClick" :activies="activies" ref="bchNavItemRef"></bch-nav-item>
            </div>
                `,
            components: {
                bchNavItem: {
                    name: 'dfc-nav',
                    template: `
                <div>
                    <div v-for="(item, index) in list" :key="index">
                        <p v-show="item.show" class="button" 
                            :class="{active: activies[item.level] == item.name}"
                            @click="itemClick(item, index)">
                            {{ item.name }}
                        </p>

                        <div v-if="item.children && item.children.length">
                            <dfc-nav class="item-box"
                            :activies="activies"
                            :class="['item-box-' + item.level]" 
                            :list="item.children">
                            </dfc-nav>
                        </div>
                    </div>
                </div>`,
                    props: {
                        list: {
                            type: Array,
                            default: () => {
                                return []
                            }
                        },
                        activies: {
                            type: Array,
                            default: () => {
                                return []
                            }
                        }
                    },
                    data() {
                        return {};
                    },
                    mounted() {
                    },
                    methods: {
                        itemClick(item, index) {
                            this.itemHide(this.list)
                            this.list.forEach(v => v.show = true)
                            this._itemClick(item)
                            this.$emit('click', item)
                        },
                        _itemClick(item) {
                            item.show = true
                            this.$set(this.activies, item.level, item.name)
                            this.activies.splice(item.level + 1)

                            if (item.children && item.children.length > 0) {
                                item.children.forEach((v, k) => {
                                    if (k == 0) this._itemClick(v)
                                    v.show = true
                                })
                            }
                        },
                        itemHide(array, name) {
                            array.forEach((v, k) => {
                                v.show = false
                                if (v.children) this.itemHide(v.children, v.name)
                            })
                        }
                    }
                }
            },
            data() {
                return {
                    list: [],
                }
            },
            methods: {
                itemClick(item) {
                    this.$emit('click', item)
                },
                calculationLevel(arr) {
                    let maxLevel = 0;
                    ! function multiArr(arr, level) {
                        ++level;
                        maxLevel = Math.max(level, maxLevel);
                        for (let i = 0; i < arr.length; i++) {
                            let item = arr[i];
                            item.level = level;
                            if (item.children && item.children.length > 0) {
                                multiArr(item.children, level);
                            } else {
                                delete item.children;
                            }
                        }
                    }(arr, 0);
                    return maxLevel;
                },
                formatToT2ree(items) {
                    let res = []
                    let getChildren = (res, pid, level = -1) => {
                        items.forEach((v, k) => {
                            if (v.pid === pid) {
                                const newItem = {
                                    ...v,
                                    show: false,
                                    children: []
                                }
                                if (newItem.pid === 0) {
                                    newItem.show = true
                                }
                                newItem.level = level
                                res.push(newItem)
                                getChildren(newItem.children, newItem.id, ++newItem.level)
                            }
                        })
                    }
                    getChildren(res, 0)
                    return res
                },
            },
            mounted() {
                this.list = this.formatToTree(this.data)
                setTimeout(() => {
                    this.$refs.bchNavItemRef.itemClick(this.list[0])
                }, 0)
            }
        }

 

posted @ 2021-11-29 18:35  白超华  阅读(204)  评论(0编辑  收藏  举报