持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
递归组件在我们日常使用的过程当中,这个用法虽然说不会经常是使用,但是我们还是需要知道他的使用方法,比如让我们自己写一个侧边菜单栏,可能会包括n多级,再比如我们下面这种表单,组件递归只能用在有子属性的数据,下面我们就介绍其中一种的用法。
我们可以看下我们要循环递归的数据
export const comdata = [
{
id: 1,
name: '小明',
age: 44,
children: [
{
id: 2,
name: '小李',
age: 43,
},
{
id: 3,
name: 'Rose',
age: 22,
children: [
{
id: 4,
name: '小张',
age: 44
},
{
id: 5,
name: 'JJJ',
age: 4
}
],
}
],
},
{
id: 6,
name: 'sam',
age: 9,
children: [
{
id: 7,
name: 'jjj',
age: 44,
children: [
{
id: 8,
name: "张三",
age: 1,
}
],
}
]
},
]
上面是我们要用到的递归数据,我们在使用之前需要把他转化为响应式数据需要用到vue3的 reactive 代码我只写重要的部分,其他的地方就不行,思路会写在代码上
<customerZ :data="state.data" @setAge="setAge"></customerZ> // 和vue2一样的传递数据 接收子组件数据的方式和vue2也是一样的
import { reactive } from 'vue' // 引用reactive 将对象转化为响应式
setup() {
function setAge(id,age) { // 接收子组件方法
console.log(id,age)
}
const state = reactive({ // 用法 就不过多赘述了,我之前的文章也介绍过
data: comdata
})
return {
state,
setAge
}
}
下面就是子组件的写法,递归组件的写法还有有一些不同的
// 写这个递归组件,最重要的不是把ui渲染出来,最重视添加事件,并且每个input框的事件 相互不影响才是最重要的
<li v-for="(item,index) in props.data" :key="index">
<p>id: {{item.id}}</p>
<p>名字: {{item.name}}</p>
<p>
<span>{{item.age}}</span>
<span>
<input type="text" :value="item.age" @input="setAge(item.id,$event.target.value)">
// 上面我们给input框添加了input时间了,我们要保证每个input都是独立,我们就需要知道这个item的id了
</span>
</p>
// 上面的写法还是比较正常的
// 主要是下面的写法可能会造成一些困扰,为啥会这样写,组件的名字默认会使用文件的名称的这是vue3的特性,其实下面的写法就是在循环整个组件
<ul v-if="item.children">
<customerZ :data="item.children"></customerZ>
</ul>
</li>
// 写的并不正规,只要是描述思路 下面对父级数据的接收
export default {
props: ['data'],
setup(props,ctx) {
function setAge(id,age) {
ctx.emit("setAge",{ id,age }) // 添加emit事件
}
return {
props
}
}
}
// 接收参数的第两种写法 这个方法比较简洁,用那种方法看我们自己
<script setup>
let props = defineProps({
data: Array,
})
let emit = defineEmits([setAge])
function setAge(id,age) { // 这是我们第两种父子组件写法的方式
emit("setAge",id,age)
}
</script>
下面可以看下写好的动画,主要看打印数据
我们已经可以知道了,我们input事件是谁触发的了,说明我们的写法没有问题,