
目錄一、React children 與 Vue slot 全面對(duì)比二、從 Vue slot 的視角來理解 React children1、Vue 的默認(rèn)插槽 - 基本沒有本質(zhì)區(qū)別React children2、Vue 的具名插槽 - React 使用普通 PropsReact children3、Vue 的作用域插槽 - 兩者都能實(shí)現(xiàn)子組件向插槽內(nèi)容提供數(shù)據(jù)React children三、為什么 React 不專門設(shè)計(jì)一個(gè) Slot API四、最終總結(jié)React 的children與 Vue 的slot核心設(shè)計(jì)思想基本相同都是通過組件組合Composition讓父組件向子組件提供內(nèi)容由子組件決定這些內(nèi)容的渲染位置。但二者有一個(gè)重要區(qū)別Vue 將 Slot 設(shè)計(jì)成專門的模板插槽機(jī)制而 React 沒有獨(dú)立的 Slot API而是通過children和普通 Props 傳遞 React 節(jié)點(diǎn)實(shí)現(xiàn)類似能力??偟脕碇vReact 的children比 Vue 的slot更簡(jiǎn)約大氣一些更符合“大道至簡(jiǎn)”的路子。一、React children 與 Vue slot 全面對(duì)比對(duì)比維度Reactchildren/ PropsVueslot核心定位基于 Props 的組件組合機(jī)制專門用于組件內(nèi)容分發(fā)的插槽機(jī)制核心思想組件接收外部傳入的內(nèi)容并決定其渲染位置組件聲明插槽位置父組件提供插槽內(nèi)容默認(rèn)插槽childrenslot /具名插槽普通 Props如header、footerslot nameheader /插槽內(nèi)容傳遞傳遞 React 節(jié)點(diǎn)JSX 等傳遞模板片段底層以插槽函數(shù)表示作用域插槽通過 Render Props函數(shù) Props實(shí)現(xiàn)通過 Scoped Slots 實(shí)現(xiàn)內(nèi)容作用域JSX 通常在父組件的詞法作用域中創(chuàng)建插槽內(nèi)容通常在父組件的模板作用域中求值子組件向內(nèi)容提供數(shù)據(jù)調(diào)用函數(shù) Props 并傳入?yún)?shù)通過slot :data...暴露 Slot Props默認(rèn)內(nèi)容通過 JS 默認(rèn)值、條件判斷實(shí)現(xiàn)直接在slot內(nèi)聲明后備內(nèi)容多區(qū)域組合多個(gè) JSX Props多個(gè)具名 Slot類型約束TypeScript 定義 Props 類型defineSlots()等機(jī)制靈活性JSX、函數(shù)和 Props 組合非常自由模板語(yǔ)義明確具名和作用域插槽更直觀主要特點(diǎn)統(tǒng)一、靈活、偏 JavaScript 組合聲明式、語(yǔ)義清晰、偏模板組合二、從 Vue slot 的視角來理解 React children1、Vue 的默認(rèn)插槽 - 基本沒有本質(zhì)區(qū)別React childrenReactfunctionCard({children}){return(div classNamecard{children}/div);}Cardh2標(biāo)題/h2p內(nèi)容/p/CardVue!-- Card.vue --templatedivclasscardslot//div/template!-- 使用 --Cardh2標(biāo)題/h2p內(nèi)容/p/Card兩者效果相同父組件提供內(nèi)容Card組件決定內(nèi)容插入的位置。2、Vue 的具名插槽 - React 使用普通 PropsReact childrenReactfunctionLayout({header,footer,children}){return(header{header}/headermain{children}/mainfooter{footer}/footer/);}Layout header{Header/}footer{Footer/}Content//LayoutVue!-- Layout.vue --templateheaderslotnameheader//headermainslot//mainfooterslotnamefooter//footer/template!-- 使用 --Layouttemplate#headerHeader//templateContent/template#footerFooter//template/Layout這里 Vue 的優(yōu)勢(shì)是具有專門的插槽語(yǔ)法而 React 直接利用 JSX 作為 JavaScript 值的能力。3、Vue 的作用域插槽 - 兩者都能實(shí)現(xiàn)子組件向插槽內(nèi)容提供數(shù)據(jù)React children這一點(diǎn)是最值得理解的。普通插槽解決的是父組件向子組件傳遞什么內(nèi)容作用域插槽進(jìn)一步解決父組件提供的內(nèi)容如何使用子組件內(nèi)部的數(shù)據(jù)ReactRender PropsfunctionList({items,renderItem}){return(ul{items.map(item(li key{item.id}{renderItem(item)}/li))}/ul);}List items{users}renderItem{user(strong{user.name}/strong)}/VueScoped Slots!--List.vue--templateulli v-foritem in items:keyitem.idslot:itemitem//li/ul/template!--使用--List:itemsuserstemplate #default{ item }strong{{item.name}}/strong/template/ListReact 通過調(diào)用函數(shù)renderItem(item)將數(shù)據(jù)交給父組件定義的渲染邏輯Vue 通過slot props實(shí)現(xiàn)類似的數(shù)據(jù)傳遞。React 也可以將children本身定義為函數(shù)形成 Function as Children 模式。三、為什么 React 不專門設(shè)計(jì)一個(gè) Slot APIVue Slot 是一套專門的內(nèi)容分發(fā) APIReact children 是利用通用 Props 實(shí)現(xiàn)內(nèi)容組合的一種慣用方式。主要是兩種框架的表達(dá)方式不同Vue 是模板驅(qū)動(dòng)的框架需要通過slot、v-slot、#header等專門語(yǔ)法表達(dá)內(nèi)容的插入位置及數(shù)據(jù)關(guān)系。React 使用 JSX 作為 JavaScript 表達(dá)式JSX 可以賦值給變量、通過 Props 傳遞也可以由函數(shù)返回。因此無須引入專門的 Slot 語(yǔ)法也能完成內(nèi)容組合。這不代表 React 比 Vue 更先進(jìn)或者 Vue 的 Slot 是多余設(shè)計(jì)。兩者只是 API 設(shè)計(jì)取向不同。四、最終總結(jié)VueReact 對(duì)應(yīng)機(jī)制默認(rèn)插槽slotchildren具名插槽slot nameJSX Props作用域插槽v-slotRender Props / Function as Children插槽后備內(nèi)容默認(rèn)值或條件渲染動(dòng)態(tài)插槽名動(dòng)態(tài)選擇 Props 或組合結(jié)構(gòu)插槽內(nèi)容復(fù)用JSX 變量、組件組合、渲染函數(shù)如果從框架設(shè)計(jì)思想上理解Vue 傾向于把組件組合能力封裝成專門的模板語(yǔ)法React 傾向于利用 JavaScript 本身的表達(dá)能力實(shí)現(xiàn)組件組合。