Vue 递归组件

通过一个树状组件,研究一下组件的递归;

递归组件注意:

1. 组件要加上 name 属性;
2. 在循环中,调用自身;
3. 适当的时候结束递归;
4. 适当的数据(可以递归循环);

好了,话不多说,开始制作树状组件;

1)看一下要用的数据结构

[
    {
        name: '山东省',
        show: true,
        children: [
            {
                name: '潍坊市',
                show: true,
                children: [
                    {
                        name: '临朐县',
                        show: true,
                    },
                    {
                        name: '潍城区',
                        show: true,
                    }
                ]
            },
            {
                name: '日照市',
                show: true,
                children: [
                    {
                        name: '岚山区',
                        show: true,
                    },
                    {
                        name: '五莲县',
                        show: true,
                    }
                ]
            },
            {
                name: '济南市',
                show: true,
                children: [
                    {
                        name: '市中区',
                        show: true,
                    },
                    {
                        name: '高新区',
                        show: true,
                    }
                ]
            },
        ]
    },
    {
        name: '陕西省',
        show: true,
        children: [
            {
                name: '西安市',
                show: true,
                children: [
                    {
                        name: '未央区',
                        show: true,
                    },
                    {
                        name: '莲湖区',
                        show: true,
                        children: [
                            {
                                name: '红庙坡街道',
                                show: true,
                            },
                            {
                                name: '梨园路',
                                show: true,
                            }
                        ]
                    },
                    {
                        name: '浐灞',
                        show: true,
                    },
                ]
            },
            {
                name: '咸阳市',
                show: true,
            },
            {
                name: '汉中市',
                show: true,
            }
        ]
    }
]

2)开始编写组件

Vue.component('Tree', {
    // 【注意 1】要做递归,要加上name属性;
    // 全局组件可以不要,因为会自动生成,局部组件一定要添加上 name
    name: 'Tree',
    props: {
        treeData: Array
    },
    template: `
    <ul>
        <!--【注意 2】在循环的 li里边,调用了自身组件-->
        <li v-for="item in treeData">

            <p @click="item.show = !item.show">{{item.name}}</p>
            
            <Tree :treeData="item.children" 
                v-if="Array.isArray(item.children)" 
                v-show="item.show"/>
        </li>
    </ul>
    `,
});

解释:
treeData 是上边的数据;传入到组件中;

组件通过 <li> 循环;首先读取出地区名称来;也就是 <p>标签中的内容;
然后,需要在这个地区下面跟上下级地区的名称,数据那里来的呢,就是循环 <li> 这条数据的 children 项,就是下级数据,所以就在此处,再次调用自身;

然后通过检查 可能是下级的下级,还有没有 children项,如果没有了,就不再执行 自身<Tree> 组件了;

然后点击收起是怎么实现的呢?
<p><li> 内的 <Tree> 使用的数据是同一条,所以点击 <p> 之后,转化了状态,下边的本条数据chilren的就不可见了;


好吧,我也感觉自己没有讲解的很明白…
感觉意思明白,但是转化成文字不好描述,这个得多次练习,熟能生巧;

完整代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./vue.js"></script>
</head>

<body>

    <div id="app"></div>

    <script>
        Vue.component('Tree', {
            // 【注意 1】要做递归,要加上name属性;
            // 全局组件可以不要,因为会自动生成,局部组件一定要添加上 name
            name: 'Tree',
            props: {
                treeData: Array
            },
            template: `
            <ul>
                <!--【注意 2】在循环的 li里边,调用了自身组件-->
                <li v-for="item in treeData">

                    <p @click="item.show = !item.show">{{item.name}}</p>
                    
                    <Tree :treeData="item.children" 
                        v-if="Array.isArray(item.children)" 
                        v-show="item.show"/>
                </li>
            </ul>
            `,
        });

        new Vue({
            el: "#app",
            template: `
            <Tree :treeData="treeData"/>
            `,
            data: {
                treeData:
                    [
                        {
                            name: '山东省',
                            show: true,
                            children: [
                                {
                                    name: '潍坊市',
                                    show: true,
                                    children: [
                                        {
                                            name: '临朐县',
                                            show: true,
                                        },
                                        {
                                            name: '潍城区',
                                            show: true,
                                        },
                                        {
                                            name: '奎文区',
                                            show: true,
                                        },
                                        {
                                            name: '寿光县',
                                            show: true,
                                        }
                                    ]
                                },
                                {
                                    name: '日照市',
                                    show: true,
                                    children: [
                                        {
                                            name: '岚山区',
                                            show: true,
                                        },
                                        {
                                            name: '五莲县',
                                            show: true,
                                        }
                                    ]
                                },
                                {
                                    name: '济南市',
                                    show: true,
                                    children: [
                                        {
                                            name: '市中区',
                                            show: true,
                                        },
                                        {
                                            name: '高新区',
                                            show: true,
                                        },
                                        {
                                            name: '章区',
                                            show: true,
                                        },
                                        {
                                            name: '槐荫区',
                                            show: true,
                                        }
                                    ]
                                },
                            ]
                        },
                        {
                            name: '陕西省',
                            show: true,
                            children: [
                                {
                                    name: '西安市',
                                    show: true,
                                    children: [
                                        {
                                            name: '未央区',
                                            show: true,
                                        },
                                        {
                                            name: '莲湖区',
                                            show: true,
                                            children: [
                                                {
                                                    name: '红庙坡街道',
                                                    show: true,
                                                },
                                                {
                                                    name: '梨园路',
                                                    show: true,
                                                }
                                            ]
                                        },
                                        {
                                            name: '高新区',
                                            show: true,
                                        },
                                        {
                                            name: '浐灞',
                                            show: true,
                                        }
                                    ]
                                },
                                {
                                    name: '咸阳市',
                                    show: true,
                                },
                                {
                                    name: '汉中市',
                                    show: true,
                                }
                            ]
                        }
                    ]
            },
        })
    </script>
</body>

</html>

学如逆水行舟,不进则退!
望吾辈共勉!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章