使用reactcontext实现vueslotslot
时间:2023-04-02 16:48:19
HTML
先看vueslot实现组件,namedslotname定义和默认slot
组件这里可能是一个页面标题
一段主要内容。
还有一个。
这是一些联系信息
最终会渲染现成的结构主要内容的一段。
还有一个。
p><页脚><p>这里是一些联系方式 言归正传,如何利用react的context来实现vue的这个功能呢?1首先确认布局组件的结构{return(
)}}exportdefaultSlotProvider(AppLayout)2为这个结构输出具体内容的组件importReact,{Component}from'react';importAppLayoutfrom'./AppLayout'importAddOnfrom'./AddOn'exportdefaultclassAppextendsComponent{render(){return(
这里可能是一个页面标题
一段主要内容
另一段。
这里有一些联系方式
)}}3其中AddOn类似于模板上面的vue,所以让我们来实现这个简单的组件AddOn,它仅用于提供插槽标识和子内容importReactfrom'react';从'prop-types'constAddOn=()=>nullAddOn.propTypes={slot:PropTypes.string}AddOn.defaultTypes={slot:'$$default'}AddOn.displayName='AddOn'exportdefaultAddOn4SlotcomponentimportReactfrom'react';import{SlotContext}from'./SlotProvider'importPropTypesfrom'prop-types'constSlot=({name,children})=>{return(
{(value)=>{constaddOnRenderer=value.requestAddOnRenderer(name)return(addOnRenderer&&addOnRenderer())||children||null}})}Slot.displayName='Slot'Slot.propTypes={名称:道具类型s.string}Slot.defaultProps={name:'$$default'}exportdefaultSlot5接下来是解析Slot的HOCSlotProvider组件importReact,{Component}from'react';functiongetDisplayName(component){返回component.displayName||组件名称||'component'}exportconstSlotContext=React.createContext({requestAddOnRenderer:()=>{}})constSlotProviderHoC=(WrappedComponent)=>{returnclassextendsComponent{staticdisplayName=`SlotProvider(${getDisplayName(WrappedComponent)})`//用于缓存每个
addOnRenderers={}requestAddOnRenderer=(name)=>{if(!this.addOnRenderers[name]){returnundefined}return()=>(this.addOnRenderers[name])}render(){const{children,...restProps}=this.propsif(children){//形式为k-v存储
的内容constarr=React.Children.toArray(children)constnameChecked=[]this.addOnRenderers={}arr.forEach(item=>{constitemType=item.typeconsole.log('itemType',itemType)if(item.type.displayName==='AddOn'){constslotName=item.props.slot||'$$default'//确保内容唯一性if(nameChecked.findIndex(item=>item===slotName)!==-1){thrownewError(`Slot(${slotName})已被占用`)}this.addOnRenderers[slotName]=item.props.childrennameChecked.push(slotName)}})}return(
)}}}exportdefaultSlotProviderHoC6最终渲染结果摘录:张国宇