使用react context 實(shí)現(xiàn)vue插槽slot功能
首先來(lái)看下vue的slot的實(shí)現(xiàn)
<base-layout>組件,具名插槽name定義以及默認(rèn)插槽
<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> <template>
提供內(nèi)容渲染的組件
<base-layout> <template v-slot:header> <h1>Here might be a page title</h1> </template> <p>A paragraph for the main content.</p> <p>And another one.</p> <template v-slot:footer> <p>Here's some contact info</p> </template> </base-layout>
最終會(huì)渲染出已下架結(jié)構(gòu)
<base-layout> <template v-slot:header> <h1>Here might be a page title</h1> </template> <p>A paragraph for the main content.</p> <p>And another one.</p> <template v-slot:footer> <p>Here's some contact info</p> </template> </base-layout>
言歸正傳,怎樣使用react的context實(shí)現(xiàn)vue的這一功能呢
1 首先確認(rèn)下layout組件的結(jié)構(gòu)
import React, { Component } from 'react';
import SlotProvider from './SlotProvider'
import Slot from './Slot'
class AppLayout extends Component {
static displayName = 'AppLayout'
render () {
return (
<div className="container">
<header>
<Slot name="header"></Slot>
</header>
<main>
<Slot></Slot>
</main>
<footer>
<Slot name="footer"></Slot>
</footer>
</div>
)
}
}
export default SlotProvider(AppLayout)
2 對(duì)此結(jié)構(gòu)輸出具體內(nèi)容的組件
import React, { Component } from 'react';
import AppLayout from './AppLayout'
import AddOn from './AddOn'
export default class App extends Component {
render() {
return (
<AppLayout>
<AddOn slot="header">
<h1>這里可能是一個(gè)頁(yè)面標(biāo)題</h1>
</AddOn>
<AddOn>
<p>主要內(nèi)容的一個(gè)段落。</p>
<p>另一個(gè)段落。</p>
</AddOn>
<AddOn slot="footer">
<p>這里有一些聯(lián)系信息</p>
</AddOn>
</AppLayout>
)
}
}
3 其中AddOn類似于上面vue的template,所以下面來(lái)實(shí)現(xiàn)這個(gè)簡(jiǎn)單的只是用來(lái)提供slot標(biāo)識(shí)和children內(nèi)容的組件AddOn的實(shí)現(xiàn)
import React from 'react';
import PropTypes from 'prop-types'
const AddOn = () => null
AddOn.propTypes = { slot: PropTypes.string }
AddOn.defaultTypes = { slot: '$$default' }
AddOn.displayName = 'AddOn'
export default AddOn
4 Slot組件
import React from 'react';
import { SlotContext } from './SlotProvider'
import PropTypes from 'prop-types'
const Slot = ({ name, children }) => {
return (
<SlotContext.Consumer>
{(value) => {
const addOnRenderer = value.requestAddOnRenderer(name)
return (addOnRenderer && addOnRenderer()) || children || null
}}
</SlotContext.Consumer>
)
}
Slot.displayName = 'Slot'
Slot.propTypes = { name: PropTypes.string }
Slot.defaultProps = { name: '$$default' }
export default Slot
5 接下來(lái)就是對(duì)Slot進(jìn)行解析的HOC SlotProvider組件了
import React, { Component } from 'react';
function getDisplayName(component) {
return component.displayName || component.name || 'component'
}
export const SlotContext = React.createContext({
requestAddOnRenderer: () => { }
})
const SlotProviderHoC = (WrappedComponent) => {
return class extends Component {
static displayName = `SlotProvider(${getDisplayName(WrappedComponent)})`
// 用于緩存每個(gè)<AddOn />的內(nèi)容
addOnRenderers = {}
requestAddOnRenderer = (name) => {
if (!this.addOnRenderers[name]) {
return undefined
}
return () => (
this.addOnRenderers[name]
)
}
render() {
const {
children,
...restProps
} = this.props
if (children) {
// 以k-v的方式緩存<AddOn />的內(nèi)容
const arr = React.Children.toArray(children)
const nameChecked = []
this.addOnRenderers = {}
arr.forEach(item => {
const itemType = item.type
console.log('itemType',itemType)
if (item.type.displayName === 'AddOn') {
const slotName = item.props.slot || '$$default'
// 確保內(nèi)容唯一性
if (nameChecked.findIndex(item => item === slotName) !== -1) {
throw new Error(`Slot(${slotName}) has been occupied`)
}
this.addOnRenderers[slotName] = item.props.children
nameChecked.push(slotName)
}
})
}
return (
<SlotContext.Provider value={{ requestAddOnRenderer: this.requestAddOnRenderer }}>
<WrappedComponent {...restProps} />
</SlotContext.Provider >
)
}
}
}
export default SlotProviderHoC
6 最終渲染結(jié)果

總結(jié)
以上所述是小編給大家介紹的使用react context 實(shí)現(xiàn)vue插槽slot功能,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
React+Typescript創(chuàng)建項(xiàng)目的實(shí)現(xiàn)步驟
通過React組件庫(kù)和TypeScript的強(qiáng)類型特性,開發(fā)者可以創(chuàng)建出具有優(yōu)秀用戶體驗(yàn)和穩(wěn)定性的Web應(yīng)用程序,本文主要介紹了React+Typescript創(chuàng)建項(xiàng)目的實(shí)現(xiàn)步驟,感興趣的可以了解一下2023-08-08
React經(jīng)典面試題之倒計(jì)時(shí)組件詳解
這些天也都在面試,面試的內(nèi)容也大多千篇一律,無(wú)外乎vue、react這些框架的一些原理,和使用方法,但是也遇到些有趣的題目,這篇文章主要給大家介紹了關(guān)于React經(jīng)典面試題之倒計(jì)時(shí)組件的相關(guān)資料,需要的朋友可以參考下2022-03-03
解決React報(bào)錯(cuò)React?Hook?useEffect?has?a?missing?dependency
這篇文章主要為大家介紹了解決React報(bào)錯(cuò)React?Hook?useEffect?has?a?missing?dependency,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
React實(shí)現(xiàn)虛擬滾動(dòng)的三種思路詳解
在??web??開發(fā)的過程中,或多或少都會(huì)遇到大列表渲染的場(chǎng)景,為了解決大列表造成的渲染壓力,便出現(xiàn)了虛擬滾動(dòng)技術(shù),本文主要介紹虛擬滾動(dòng)的三種思路,希望對(duì)大家有所幫助2024-04-04
react中代碼塊輸出,代碼高亮顯示,帶行號(hào),能復(fù)制的問題
這篇文章主要介紹了react中代碼塊輸出,代碼高亮顯示,帶行號(hào),能復(fù)制的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
react實(shí)現(xiàn)可播放的進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)可播放的進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
詳解vant2 自動(dòng)檢查表單驗(yàn)證 -validate
這篇文章主要介紹了vant2 自動(dòng)檢查表單驗(yàn)證 -validate,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10
react中的useImperativeHandle()和forwardRef()用法
這篇文章主要介紹了react中的useImperativeHandle()和forwardRef()用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08

