遞迴元件組合拳,無懼頁面巢狀

發表於2024-02-24

介紹

遞迴元件在元件內巢狀元件時比較常用,我在這裡舉幾個例子:
1、後臺管理系統的menu選單
在這裡插入圖片描述

2、教育系統的題目列表
在這裡插入圖片描述
在遍歷生成基礎題時,遇到了綜合題,綜合題包含了所有基礎題,此時就不用再寫一遍基礎題,直接呼叫自身元件即可,這樣不論基礎題內部巢狀多少層綜合題,都可以生成題目列表。
在這裡插入圖片描述


如何實現遞迴元件?

父頁面:正常引入元件

// 父頁面
<template>
    <div>
        <Circulation :dataInfo="dataInfo"/>
    </div>
</template>
 
<script>
import Circulation from '@/views/circulation.vue'
export default {
    components: { Circulation },
    data() {
        return {
          dataInfo: [
            // ......
          ]
        }
    },
}
</script>

子元件

// circulation頁面
<template>
    <div>
       <div v-for="item in dataInfo"></div>
        // 其它邏輯......

        // 假如遇到children -> 複用自身 
        <Circulation :dataInfo="item.children"/>
    </div>
</template>
 
<script>
export default {
    name: 'Circulation', // 一定要設定name,於元件名相同
    props: {
        dataInfo: {
            type: Array,
            default: () => {
                return []
            }
        },
    },
}
</script>

上面的程式碼就實現了遞迴元件,在子元件中不需要引入自身,只需要設定name,然後透過name複用元件即可
下面是你在教育型別專案中會遇到的場景:
在這裡插入圖片描述


注意點

1、事件冒泡
注意:遞迴元件的事件一定要用.stop阻止冒泡,否則會報錯
例如:@click.stop="onClose(item)"

2、prop值更新
在遞迴元件中透過事件更改prop的值時,會報錯,提示請避免在子元件中對prop進行直接更改
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "questionList"
避免直接更改 prop,因為每當父元件重新渲染時,該值都會被覆蓋。相反,請使用基於道具值的資料或計算屬性。被變異的道具:"questionList"
遞迴元件儘量避免直接對prop進行修改,哪怕你使用了計算屬性,也會報錯提示。

3、遞迴元件深層事件
由於是遞迴元件,層級的巢狀可能會很深,但是頁面只有當前這一個,如果只處理當前層級的邏輯可以直接@click.stop="xxx"觸發
如果需要將事件向父級回傳,則需要使用emit,並且自身頁面的遞迴元件上也需要設定事件,例如:

// 父頁面
<template>
    <div>
        <Circulation :dataInfo="dataInfo" @onChange="onChange"/>
    </div>
</template>
<script>
import Circulation from '@/views/circulation.vue'
export default {
    components: { Circulation },
    data() {
        return {
          dataInfo: [
            // ......
          ]
        }
    },
    methods: {
      // 觸發事件 
      onChange() {},
    }
}
</script>

子頁面

// circulation頁面
<template>
    <div>
       <div v-for="item in dataInfo"></div>
        // 其它邏輯......

        // 假如遇到children -> 複用自身 
        <Circulation :dataInfo="item.children"  @onChange="onChange"/>
    </div>
</template>
 
<script>
export default {
    name: 'Circulation', // 一定要設定name,於元件名相同
    props: {
        dataInfo: {
            type: Array,
            default: () => {
                return []
            }
        },
    },
    methods: {
      // 觸發回傳
      onChange() {
        this.$emit('onChange')
      },
    }
}
</script>

這樣做它的回傳事件會層層遞迴,直到返回最上層。
在渲染層面,它是層層遞。
在事件回傳層面,它是層層歸。


如果覺得該元件不錯,歡迎點贊👍、收藏💖、轉發✨哦~

閱讀其它:

微信小程式使用者隱私API(👈點選直達)

前端換膚,聊一聊主題切換那些事(👈點選直達)

Shapes佈局-文字環繞動畫(👈點選直達)

css繪製一個Pinia小菠蘿(👈點選直達)

深入理解Promise(👈點選直達)

相關文章