Vue学习笔记 利用Vue 实现树形视图

这是学习代码以来的第一篇文章

利用简单的树形视图实现,熟悉了组件的递归使用

这是模拟的树形图数据

let all={
        name:'all',
        children:{
            A:{
                name:'A',
                children:{
                    a1:{
                        name:'a1',
                        children:{
                            a11:{   
                                name:'a11',
                                children:null
                            },
                            a12:{   
                                name:'a12',
                                children:null
                            }
                        }
                    },
                    a2:{
                        name:'a2',
                        children:{
                            b21:{   
                                name:'b21',
                                children:null
                            }
                        }
                    }
                }
            },
           B:{
                name:'B',
                children:{
                    b1:{
                        name:'b1',
                        children:{
                            b11:{   
                                name:'b11',
                                children:null
                            },
                            b12:{   
                                name:'b12',
                                children:null
                            }
                        }
                    },
                    b2:{
                        name:'b2',
                        children:{
                            b21:{   
                                name:'b21',
                                children:null
                            }
                        }
                    }
                }
            }
        }
    }


代码如下

treelist.vue

<template>
<div>
    <ul>
        <li   >
            <span @click="isshow()">{{treelist.name}}</span>
                <tree  v-for="item in treelist.children"   
                    v-if="isFolder"
                    v-show="open" 
                    :treelist="item" 
                    :keys="item"
                ></tree>
        </li>
    </ul>
</div>
  
</template>
<script>
export default {
    name:'tree',
    props:['treelist'],
    data(){
        return{
            open:false
        }
    },computed:{
        isFolder:function(){
            return this.treelist.children
         }
        }
    ,methods:{
        isshow(){
            if (this.isFolder) {
                this.open =!this.open
            }
        }
    }
}
</script>
<style lang="less">


</style>

index.html

<!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>树形图</title>
</head>
<body>
    <div id="app">
        <tree :treelist="treeList"></tree>
       
    </div> 
</body>
</html>

index.js

import Vue from 'vue';

import tree from '../components/treelist.vue'

let all={
        name:'all',
        children:{
            A:{
                name:'A',
                children:{
                    a1:{
                        name:'a1',
                        children:{
                            a11:{   
                                name:'a11',
                                children:null
                            },
                            a12:{   
                                name:'a12',
                                children:null
                            }
                        }
                    },
                    a2:{
                        name:'a2',
                        children:{
                            b21:{   
                                name:'b21',
                                children:null
                            }
                        }
                    }
                }
            },
           B:{
                name:'B',
                children:{
                    b1:{
                        name:'b1',
                        children:{
                            b11:{   
                                name:'b11',
                                children:null
                            },
                            b12:{   
                                name:'b12',
                                children:null
                            }
                        }
                    },
                    b2:{
                        name:'b2',
                        children:{
                            b21:{   
                                name:'b21',
                                children:null
                            }
                        }
                    }
                }
            }
        }
    }
    






const app=new Vue({
    el:"#app",
    components:{
        'tree':tree
    },
    data:{
        treeList:all 
    }
})

在经过踩坑之后,我发现Vue官网有类似的案例,链接→ 传送门

参考过官网的方法后,我尝试着实现了一下


这样写和我踩坑时的 思路不同点在于, 这样一个组件只负责一个 对象,遍历每个children 中的对象,逐个传入组件处理,而我第一次尝试则是 将整个children  传入自身   是一个组件处理多个对象,(第一次尝试的失败案例,有兴趣请看最下方)

这样一个组件处理一个对象 写的好处是什么呢

我可以在组件内自定义开关了

我在data里定义了变量open,因为组件递归,所以相当于每个组件都有个属于自己的open

那为什么第一次踩坑时我不可以用这种方法呢,因为我第一次尝试 是一个组件处理多个对象 就是相当于 一个开关控制 children中的所有对象,当开关打开时会导致 这个同级的所有 对象都被展开


遍历children 挨个传入组件自身    用v-show 来控制是否显示 




定义了一个计算属性,依据children来判断是否继续执行 



在span标签上绑定了一个自定义事件

更改open 的值 

<span @click="isshow()">{{treelist.name}}</span>

实现效果





以下 是我刚开始尝试的时候踩得坑

在这里记录一下,以后遇到类似问题留个印象

首先上来就遇到了这样的报错


找了很久的问题,发现是因为组件内忘记写name了,自身使用自身必须填写name,并且与标签名一致


一开始的实现方法,利用组件递归,显示出当前级的name渲染出来,并将其中的 children 中的所有对象 传给自己然后接着执行相同操作,直到children没有数据,值得一提的是,如果这里不加上 v-if 就会变成 死循环,就会一直执行下去,所以我们要判断一下当前执行的对象到底还有没有下一级

这里我数据有稍微的改动,所以我第一次传入的数据就是(index.html页面)


然后我定义了一个事件来处理 每一层的关闭和开启,我用弹框来查看Isopen 的值是否被改变


我们看一下结果

刚进入页面时,括号中的undefined是 Isopen 当前的值,因为此时未被定义,所以为undefined


然后我点击了A


因为此时isopen已被反转值,所以此时isopen为true


但是页面仍毫无变化,不说展开功能,就连undefined也没变化



经过一番百度 ,发现原来是vue本身已经不允许这样直接更改 Props接受过来的值了

Vue2.0以后子组件不能更改父组件的值,只能通过子组件$emit(),父组件$on()进行响应更改

第一次写文章,语言描述能力还有欠缺,望大家见谅,哪里有不对的麻烦大家指出,这也是互相学习的过程,

希望大家如果遇到类似问题不要被困扰太久,

溜了溜了~
  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值