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


Posted in Javascript onJuly 18, 2019

首先来看下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功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
简单三步,搞掂内存泄漏
Mar 10 Javascript
JavaScript 对象模型 执行模型
Oct 15 Javascript
JS TextArea字符串长度限制代码集合
Oct 31 Javascript
JavaScript操纵窗口的方法小结
Jun 28 Javascript
js下将阿拉伯数字每三位一逗号分隔(如:15000000转化为15,000,000)
Jun 02 Javascript
使用变量动态设置js的属性名
Oct 19 Javascript
一个不错的js html页面倒计时可精确到秒
Oct 22 Javascript
node.js中的http.response.getHeader方法使用说明
Dec 14 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐)
Jun 23 Javascript
KnockoutJS 3.X API 第四章之表单value绑定
Oct 10 Javascript
js中数组常用方法总结(推荐)
Apr 09 Javascript
Vue使用JSEncrypt实现rsa加密及挂载方法
Feb 07 Javascript
jquery图片预览插件实现方法详解
Jul 18 #jQuery
vue使用自定义指令实现拖拽
Jan 29 #Javascript
对TypeScript库进行单元测试的方法
Jul 18 #Javascript
基于JS实现数字动态变化显示效果附源码
Jul 18 #Javascript
微信小程序实现拍照画布指定区域生成图片
Jul 18 #Javascript
vue使用video.js进行视频播放功能
Jul 18 #Javascript
百度小程序之间的页面通信过程详解
Jul 18 #Javascript
You might like
初品cakephp 入门基础
2012/02/16 PHP
php 使用mpdf实现指定字段配置字体样式的方法
2019/07/29 PHP
JS 学习笔记 防止发生命名冲突
2009/07/30 Javascript
jQuery的实现原理的模拟代码 -3 事件处理
2010/08/03 Javascript
最新28个很棒的jQuery 教程
2011/05/28 Javascript
JavaScript中this关键词的使用技巧、工作原理以及注意事项
2014/05/20 Javascript
jQuery实现简单网页遮罩层/弹出层效果兼容IE6、IE7
2014/06/16 Javascript
JQuery实现展开关闭层的方法
2015/02/17 Javascript
JQuery中基础过滤选择器用法实例分析
2015/05/18 Javascript
jQuery实现可以控制图片旋转角度效果(附demo源码下载)
2016/01/27 Javascript
Bootstrap CSS布局之图像
2016/12/17 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
2017/02/03 Javascript
微信小程序商城项目之商品属性分类(4)
2017/04/17 Javascript
vue 实现 tomato timer(蕃茄钟)实例讲解
2017/07/24 Javascript
原生js jquery ajax请求以及jsonp的调用方法
2017/08/04 jQuery
nodejs 图片预览和上传的示例代码
2017/09/30 NodeJs
详解JS数值Number类型
2018/02/07 Javascript
微信公众号生成新浪短网址的实现(快速生成)
2019/08/18 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
Python正则抓取网易新闻的方法示例
2017/04/21 Python
python实现数据预处理之填充缺失值的示例
2017/12/22 Python
Python中按键来获取指定的值
2019/03/02 Python
python中的列表与元组的使用
2019/08/08 Python
基于python plotly交互式图表大全
2019/12/07 Python
python编程进阶之异常处理用法实例分析
2020/02/21 Python
Python图像处理库PIL的ImageEnhance模块使用介绍
2020/02/26 Python
Tensorflow tf.nn.atrous_conv2d如何实现空洞卷积的
2020/04/20 Python
Pytorch转keras的有效方法,以FlowNet为例讲解
2020/05/26 Python
Python matplotlib可视化实例解析
2020/06/01 Python
荷兰网上买鞋:MooieSchoenen.nl
2017/09/12 全球购物
Bluebella法国官网:英国性感内衣品牌
2019/05/03 全球购物
客户经理岗位职责
2013/12/08 职场文书
2014年乡镇妇联工作总结
2014/12/02 职场文书
出纳年终工作总结2014
2014/12/05 职场文书
小平您好观后感
2015/06/09 职场文书
nginx处理http请求实现过程解析
2021/03/31 Servers