Vue2、Vue3中的$scopedSlots和$slots區(qū)別小結
$scopedSlots(作用域插槽)
定義:子組件提供數(shù)據(jù),父組件決定如何渲染,數(shù)據(jù)作用域屬于子組件。
本質:子組件不直接渲染內容,而是接收一個函數(shù),這個函數(shù)在子組件作用域內執(zhí)行,從而讓父組件的模板可以訪問子組件的數(shù)據(jù)。
// 作用域插槽的本質:一個函數(shù),子組件調用時傳入數(shù)據(jù)
this.$scopedSlots.default = function(data) {
// 這個函數(shù)在父組件的作用域編譯
// 但參數(shù) data 來自子組件
return VNode // 返回渲染好的節(jié)點
}$slots(普通插槽)
定義:父組件提供內容,子組件決定在哪里渲染,數(shù)據(jù)作用域屬于父組件。
本質:父組件在編譯時就已經(jīng)確定了插槽內容的所有數(shù)據(jù)和邏輯,子組件只是作為一個容器來擺放這些內容。
// 普通插槽的本質:父組件編譯好的 VNode 數(shù)組 // 子組件只是被動接收 this.$slots.default = [VNode, VNode, ...] // 已經(jīng)是渲染好的節(jié)點
數(shù)據(jù)作用域的指向
<!-- 父組件 Parent.vue -->
<template>
<div>
<!-- 普通插槽 -->
<ChildComponent>
<div>{{ parentMessage }}</div> <!-- ? 可以訪問父組件數(shù)據(jù) -->
<!-- <div>{{ childMessage }}</div> ? 不能訪問子組件數(shù)據(jù) -->
</ChildComponent>
<!-- 作用域插槽 -->
<ChildComponent>
<template v-slot:default="slotProps">
<div>{{ parentMessage }}</div> <!-- ? 可以訪問父組件數(shù)據(jù) -->
<div>{{ slotProps.childMessage }}</div> <!-- ? 可以訪問子組件數(shù)據(jù) -->
</template>
</ChildComponent>
</div>
</template>
<script>
export default {
data() {
return {
parentMessage: '父組件的數(shù)據(jù)' // 父組件作用域
}
}
}
</script><!-- 子組件 ChildComponent.vue -->
<template>
<div>
<!-- 普通插槽:直接渲染父組件傳來的內容 -->
<slot></slot>
<!-- 作用域插槽:將子組件數(shù)據(jù)傳遞給父組件 -->
<slot :childMessage="childMessage"></slot>
</div>
</template>
<script>
export default {
data() {
return {
childMessage: '子組件的數(shù)據(jù)' // 子組件作用域
}
}
}
</script>編譯時 vs 運行時
普通插槽:編譯時確定
// 父組件模板
<template>
<child>
<span>{{ message }}</span> <!-- message 在編譯時就綁定到父組件 -->
</child>
</template>
// 編譯后的渲染函數(shù)(簡化)
render() {
// 在父組件作用域中創(chuàng)建 VNode
const children = [createVNode('span', null, this.message)]
// 傳遞給子組件
return h(Child, null, { default: () => children })
}作用域插槽:運行時確定
// 父組件模板
<template>
<child>
<template v-slot="props">
<span>{{ props.message }}</span> <!-- message 來自子組件 -->
</template>
</child>
</template>
// 編譯后的渲染函數(shù)(簡化)
render() {
// 父組件不直接創(chuàng)建 VNode,而是創(chuàng)建一個函數(shù)
const scopedSlotFn = (props) => {
return createVNode('span', null, props.message)
}
// 把這個函數(shù)傳遞給子組件
return h(Child, null, { default: scopedSlotFn })
}
// 子組件中
render() {
// 子組件調用這個函數(shù),傳入自己的數(shù)據(jù)
const vnode = this.$scopedSlots.default({ message: this.childMessage })
return vnode
}總結對比表
| 維度 | 普通插槽 | 作用域插槽 |
|---|---|---|
| 數(shù)據(jù)來源 | 父組件 | 子組件 |
| 存儲形式 | VNode數(shù)組 | 函數(shù) |
| 編譯時機 | 父組件編譯時 | 子組件運行時調用 |
| 使用場景 | 布局、內容填充 | 自定義渲染,列表渲染 |
| 靈活性 | 低(內容固定) | 高(可動態(tài)渲染) |
| 數(shù)據(jù)流向 | 父 → 子(僅傳遞內容) | 子 → 父 (僅傳遞數(shù)據(jù)) |
vue3變化,scopedSlots被移除,統(tǒng)一使用scopedSlots被移除,統(tǒng)一使用scopedSlots被移除,統(tǒng)一使用slots,所有插槽都是函數(shù)。
<!-- 子組件 Child.vue -->
<template>
<div>
<!-- 普通插槽 -->
<slot></slot>
<!-- 作用域插槽 -->
<slot name="item" :data="itemData"></slot>
</div>
</template>
<script setup>
import { onMounted } from 'vue'
const itemData = { name: 'Vue 3', version: 3 }
onMounted(() => {
// Vue 3 中,所有插槽都是函數(shù)
console.log(typeof $slots.default) // 'function'
console.log(typeof $slots.item) // 'function'
// 調用函數(shù)獲取 VNode
const defaultVNode = $slots.default()
const itemVNode = $slots.item({ data: itemData })
// 注意:Vue 3 中 $slots 返回的是 VNode 數(shù)組
console.log(Array.isArray(defaultVNode)) // true
})
</script>| 特性 | Vue 2 | Vue 3 |
|---|---|---|
| 普通插槽存儲 | $slots (VNode 數(shù)組) | $slots (函數(shù)) |
| 作用域插槽存儲 | $scopedSlots (函數(shù)) | $slots (函數(shù)) |
| 模板語法 | slot + slot-scope | 統(tǒng)一 v-slot 或 # |
| 訪問方式 | this.$slots / this.$scopedSlots | useSlots() 或 $slots |
| 類型判斷 | Array.isArray($slots.default) | typeof $slots.default === 'function' |
| 調用方式 | 普通插槽直接使用,作用域插槽需調用 | 所有插槽都需調用 |
到此這篇關于Vue2、Vue3中的$scopedSlots和$slots區(qū)別小結的文章就介紹到這了,更多相關Vue3中的$scopedSlots和$slots區(qū)別內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue?element-plus中el-input修改邊框border的方法
element樣式還是蠻好的,只是有時候我們需要做一些調整,比如el-input的邊框,下面這篇文章主要給大家介紹了關于vue?element-plus中el-input修改邊框border的相關資料,需要的朋友可以參考下2022-09-09
去掉vue 中的代碼規(guī)范檢測兩種方法(Eslint驗證)
我們在使用vue 腳手架時,為了規(guī)范團隊的代碼格式,會有一個代碼規(guī)范檢測,如果不符合規(guī)范就會報錯,有時候我們不想按照他的規(guī)范去寫。這時我們需要關閉,這里腳本之家小編給大家?guī)砹巳サ魐ue 中的代碼規(guī)范檢測兩種方法(Eslint驗證),一起看看吧2018-03-03
vue3+elementui-plus實現(xiàn)無限遞歸菜單示例代碼
這篇文章主要介紹了vue3+elementui-plus實現(xiàn)無限遞歸菜單,當一個組件的 key 值發(fā)生變化時,Vue 會認為這是一個新的組件實例,會強制重新創(chuàng)建和渲染這個組件,本文通過示例代碼詳細講解,需要的朋友可以參考下2024-04-04
proxy代理不生效以及vue?config.js不生效解決方法
在開發(fā)Vue項目過程中,使用了Proxy代理進行數(shù)據(jù)劫持,但是在實際運行過程中發(fā)現(xiàn)代理并沒有生效,也就是說數(shù)據(jù)并沒有被劫持,這篇文章主要給大家介紹了關于proxy代理不生效以及vue?config.js不生效解決方法的相關資料,需要的朋友可以參考下2023-11-11
vue使用vuedraggable插件實現(xiàn)拖拽效果
這篇文章主要介紹了vue使用vuedraggable插件實現(xiàn)拖拽效果,本文分步驟介紹了安裝vuedraggable插件的方法及頁面引入的方法,需要的朋友可以參考下2024-04-04

