赞
踩
首先我们分析数据的结构
treeOptions:[ { lable:'一级', children:[ { lable:'一级-1' }, { lable:'一级-2' } ] }, { lable:'二级', children:[ { lable:'二级-1', children:[ { lable:'二级-1-1' }, { lable:'二级-1-2' } ] }, { lable:'二级-2' } ] }, { lable:'三级' } ]
对于这种数组类型的取值,首先想到的是
v-for
,但是我们不能准确的知道需要使用多少个v-for。如果所有的子项中children的层级是一样的
(比如下面的情况),那可以使用。但是问题是现在的数据有的item会有4层的children,有的item会有10层的children,层级不一样
,这个时候,我们可以考虑递归
// 数据的格式 // 如果是这种类型的,我们可以使用v-for进行渲染,写两层v-for。label就渲染出来了。 treeOptions:[ { lable:'一级', children:[ { lable:'一级-1' }, { lable:'一级-2' } ] }, { lable:'二级', children:[ { lable:'二级-1' }, { lable:'二级-2' } ] }, { lable:'三级', children:[ { lable:'三级-1' }, { lable:'三级-2' } ] } ] // 但是这样的数据结构,没法知道具体用几个v-for,这个时候,我们可以考虑用递归的方式解决问题。 treeOptions:[ { lable:'一级', children:[ { lable:'一级-1' }, { lable:'一级-2' } ] }, { lable:'二级', children:[ { lable:'二级-1', children:[ { lable:'二级-1-1' }, { lable:'二级-1-2' } ] }, { lable:'二级-2' } ] }, { lable:'三级' } ]
步骤:
// Tree.vue <template> <li v-for="(item,index) in Options" :key="index"> {{ item.lable }} <!-- 当没有children的时候,就不用走递归了。--> <ul v-if="item.children&&item.children.length"> <MyTree :options="item.children"></MyTree> </ul> </li> </template> <script setup> import {ref} from "vue"; const prop = defineProps({ options: { type: Array, default: () => { return [] } } }) //console.log(prop.options) </script> <style scoped> </style>
// App.vue <template> <h5>树型组件</h5> <Mtree :options="treeOptions" /> </template> <script setup> import {reactive} from "vue"; const state = reactive({ treeOptions:[ { lable:'一级', children:[ { lable:'一级-1' }, { lable:'一级-2' } ] }, { lable:'二级', children:[ { lable:'二级-1', children:[ { lable:'二级-1-1' }, { lable:'二级-1-2' } ] }, { lable:'二级-2' } ] }, { lable:'三级' } ] }) const { treeOptions } = state </script> <style scoped> </style>
=<template> <li v-for="(item,index) in myOptions" :key="index" @click.stop="openUl(item)"> {{ item.lable }} <!-- 当没有children的时候,就不用走递归了。--> <ul v-if="item.children&&item.children.length" v-show="item.isOpen"> <MyTree :options="item.children"></MyTree> </ul> </li> </template> <script setup> /* 重点:通过isOpen属性的true,false,来使组件是否v-show隐藏显示 方法: 1 添加myOptions ,使之双向绑定,绑定的数据来自prop.options传来的数据,不直接用prop.options传来数据的原因是因为要加isOpen,防止原数据遭到污染。 const myOptions = ref(prop.options); 2 在递归组件上添加v-show="item.isOpen" 用于显示与隐藏 3 在根组件上添加 @click.stop="openUl(item)" const openUl= (item)=>{ item.isOpen = !item.isOpen } 加上.stop为了防止事件冒泡 * */ import {ref} from "vue"; const prop = defineProps({ options: { type: Array, default: () => { return [] } } }) //console.log(prop.options) /* * 点击以后,展开ul,再点击,关闭ul * */ const myOptions = ref(prop.options); const openUl= (item)=>{ item.isOpen = !item.isOpen } </script> <style scoped> </style>
关于使用v-for 和 递归时候,数据是怎么渲染出来的分析。
// v-for的形式 treeOptions:[ { lable:'一级', children:[ { lable:'一级-1', //......下面有1万层children } ] }, { lable:'二级', children:[ { lable:'二级-1', //......下面有1万层children } ] } ] // 使用v-for的写法: <div v-for='(item,index) in Data'> <div v-for='(childItem,childIndex) in item.children'> ...... </div> </div> 这个时候会先渲染 "一级" ,再渲染"一级-1","一级-1-1", ...... "一级-1-1...-10000" 紧接着:"二级" ,再渲染"二级-1","二级-1-1", ...... "二级-1-1...-10000"
// 递归的形式 treeOptions:[ { lable:'一级', children:[ { lable:'一级-1', //......下面有1万层children } ] }, { lable:'二级', } ] // 这个时候,如果使用v-for就不行了。为了渲染item1,需要写10000个v-for,但是item2只需要写一个v-for。 // 这个时候,递归发挥作用了,每次都是自己调用自己,传入的值总是children。当children没有的时候,再渲染item2,也就是"二级" 这个时候会先渲染 "一级" ,再渲染"一级-1","一级-1-1", ...... "一级-1-1...-10000" 再渲染 "二级"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。