preface

In real life, we often encounter a Tree list. Here we try to implement a Tree component by ourselves.

The main idea

Use recursion for the Vue component to determine whether the node contains child nodes, and if so, recurse the component.

Development environment and development tools

  1. Development tools: VS Code;
  2. Framework: the Vue
  3. Icon library: Font Awesome

Specific code

    <div id="app">
        <sb-tree :data="list1"></sb-tree>
        <sb-tree :data="list2" :keys="keys"></sb-tree>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.component('sb-tree', {
            props: {
                data: {
                    type: Array,
                    required: true
                },
                keys: {
                    type: Object,
                    validator: function(val) {
                        let keys = Object.keys(val);
                        return keys.includes('label')&&keys.includes('children');
                    },
                    default () {
                        return {
                            label: 'label',
                            children: 'children'}}}},data() {
                return {
                    mylist: this.data.map(r=>{
                        return {
                            label: r[this.keys.label],
                            children: r[this.keys.children],
                            isShow: false}})}}, // version 2, the array attribute name template: '<ul> <li v-for="item in mylist" style="margin:10px; list-style:none;">
                    <i class="fa" aria-hidden="true" v-if="item.children&&item.children.length" :class="item.isShow? 'fa-angle-down':'fa-angle-right'"></i>
                    <span @click="item.isShow=! item.isShow">{{item.label}}</span>
                    <sb-tree style="padding:5px" v-show="item.isShow" :keys="keys" v-if="item.children&&item.children.length" :data="item.children"> < / sb - tree > < / li > < / ul > `, / / version 1, array attribute name must be a label and children / / template: ` / / < ul > / / < li v - for ="item in data">
            //         {{item.label}}
            //         <sb-tree v-if="item.children&&item.children.length" :data="item.children"></sb-tree>
            //     </li>
            // </ul>
            // `,

        })

        new Vue({
            el: "#app".data() {
                return {
                    keys: {
                        label: 'name',
                        children: 'cc'
                    },
                    list2: [{
                            name: 'A',
                            cc: [{
                                name: 'A-1',
                                cc: [{
                                    name: 'A-1-1',
                                    cc: [{
                                        name: 'A-1-1-1',
                                        cc: []
                                    }]
                                }, ]
                            }]
                        },
                        {
                            name: 'B',
                            cc: [{
                                name: 'B-1',
                                cc: []
                            }]
                        },
                    ],
                    list1: [{
                            label: 'A',
                            children: [{
                                    label: 'A-1',
                                    children: []
                                },
                                {
                                    label: 'A-2',
                                    children: [{
                                        label: 'A-2-1',
                                        children: []
                                    }, ]
                                },
                            ]
                        },
                        {
                            label: 'B',
                            children: []
                        },
                        {
                            label: 'C',
                            children: []
                        },
                    ],
                }
            },
            methods: {

            },
        })
    </script>
Copy the code

The component sB-tree requires data as an argument. Here we use props as a required property and keys as an optional property.

Keys gives the caller the freedom to define the component’s node name and child node name. Consider the label and children for List1 in this case. List2 uses custom attribute names name and cc.

To keep the original data intact, copy and process the original data using myList in the component, and add an isShow property to show or hide the child nodes.

The effect is shown below:

When a node is clicked, the click event is emitted, which inverts isShow if isShow is false and displays the child nodes, or inverts isShow if isShow is true and hides the child nodes.