一個簡單的例子:
- 父組件僅僅是調用了子組件
- 子組件內部實現了一個todolist列表
整個數據傳遞的流程:
- 1.父組件傳遞了todos數組給子組件
- 2.子組件通過props接受了數組數據,這裏應該沒有任何問題
- 3.子組件拿到數組後v-for渲染列表,並且通過 <slot :todo="todo">的方式,把數組內的每一個todo對象,傳遞給父組件
- 4.父組件通過slot-scope="slotProps"的方式,接受todo對象,之後就可以通過slotProps.todo.xxx的方式來使用了
所以數據的流動經歷了
- 父組件傳遞todos數組給子組件
- 子組件遍歷todos數組,把裏面的todo對象傳遞給父組件
源碼(父組件):
<template>
<todo-list :todos="todos">
<template slot-scope="slotProps">
<span v-if="slotProps.todo.isComplete">✓</span>
<span>{{slotProps.todo.text}}</span>
</template>
</todo-list>
</template>
<script>
import todoList from './todoList'
export default {
data () {
return {
todos: [
{
id: 0,
text: 'ziwei0',
isComplete: false
},
{
text: 'ziwei1',
id: 1,
isComplete: true
},
{
text: 'ziwei2',
id: 2,
isComplete: false
},
{
text: 'ziwei3',
id: 3,
isComplete: false
}
]
}
},
components: {
todoList
},
}
</script>
子組件:
<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
<slot :todo="todo">
</slot>
</li>
</ul>
</template>
<script>
export default {
props: {
todos: {
type: Array
}
}
}
</script>
列表組件的循環,是發生在組件內部的,所以通過 v-for="todo in todos" ,列表組件很容易拿到每一項todo,但列表拿到數據沒用呀,列表只是一個瓜皮,它又不懂業務邏輯
這個數據是你同事的業務數據,所以這個數據必須得交給組件的調用者,也就是把數據交給你的同事纔對。
那麼你怎樣才能把每一項的todo數據給傳遞出去呢?
你會發現沒有辦法!
無論是用$emit、vuex還是localStorage,可以考慮一下,會發現沒有合適的時機,能讓你把todo傳遞出去
所以爲了應對這個場景下,發明了作用域插槽,列表組件可以通過<slot :todo="todo"></slot>傳遞todo出去
你的同事可以通過 slot-scope="slotsProps"拿到todo。