最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

使用react context 实现vue插槽slot功能

来源:动视网 责编:小采 时间:2020-11-27 21:53:34
文档

使用react context 实现vue插槽slot功能

使用react context 实现vue插槽slot功能:首先来看下vue的slot的实现 <base-layout>组件,具名插槽name定义以及默认插槽 <div class=container> <header> <slot name=header></slot> </header> <main&g
推荐度:
导读使用react context 实现vue插槽slot功能:首先来看下vue的slot的实现 <base-layout>组件,具名插槽name定义以及默认插槽 <div class=container> <header> <slot name=header></slot> </header> <main&g


首先来看下vue的slot的实现

<base-layout>组件,具名插槽name定义以及默认插槽

<div class="container">
 <header>
 <slot name="header"></slot>
 </header>
 <main>
 <slot></slot>
 </main>
 <footer>
 <slot name="footer"></slot>
 </footer>
</div>
<template>

提供内容渲染的组件

<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>

最终会渲染出已下架结构

<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实现vue的这一功能呢

1 首先确认下layout组件的结构

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 对此结构输出具体内容的组件

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>这里可能是一个页面标题</h1>
 </AddOn>
 <AddOn>
 <p>主要内容的一个段落。</p>
 <p>另一个段落。</p>
 </AddOn>
 <AddOn slot="footer">
 <p>这里有一些联系信息</p>
 </AddOn>
 </AppLayout>
 )
 }
}

3 其中AddOn类似于上面vue的template,所以下面来实现这个简单的只是用来提供slot标识和children内容的组件AddOn的实现

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 接下来就是对Slot进行解析的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)})`
 // 用于缓存每个<AddOn />的内容
 addOnRenderers = {}
 requestAddOnRenderer = (name) => {
 if (!this.addOnRenderers[name]) {
 return undefined
 }
 return () => (
 this.addOnRenderers[name]
 )
 }
 render() {
 const {
 children,
 ...restProps
 } = this.props
 if (children) {
 // 以k-v的方式缓存<AddOn />的内容
 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'
 // 确保内容唯一性
 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 最终渲染结果

总结

以上所述是小编给大家介绍的使用react context 实现vue插槽slot功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

文档

使用react context 实现vue插槽slot功能

使用react context 实现vue插槽slot功能:首先来看下vue的slot的实现 <base-layout>组件,具名插槽name定义以及默认插槽 <div class=container> <header> <slot name=header></slot> </header> <main&g
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top