使用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 相关文章推荐
Javascript注入技巧
Jun 22 Javascript
IE iframe的onload方法分析小结
Jan 07 Javascript
一些经常会用到的Javascript检测函数
May 31 Javascript
关于JavaScript中name的意义冲突示例介绍
May 29 Javascript
JavaScript中的document.referrer在各种浏览器测试结果
Jul 18 Javascript
jquery禁止回车触发表单提交
Dec 12 Javascript
Bootstrap框架的学习教程详解(二)
Oct 18 Javascript
js复制内容到剪贴板代码,js复制代码的简单实例
Oct 27 Javascript
vue.js中父组件调用子组件的内部方法示例
Oct 22 Javascript
Vue子组件向父组件通信与父组件调用子组件中的方法
Jun 22 Javascript
操作按钮悬浮固定在微信小程序底部的实现代码
Aug 02 Javascript
vue 点击其他区域关闭自定义div操作
Jul 17 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
常用星际术语索引(新手指南)
2020/03/04 星际争霸
Discuz 模板引擎的封装类代码
2008/07/18 PHP
php数组总结篇(一)
2008/09/30 PHP
PHP使用feof()函数读文件的方法
2014/11/07 PHP
php检查日期函数checkdate用法实例
2015/03/19 PHP
php实现在站点里面添加邮件发送的功能
2020/04/28 PHP
javascript 简单高效判断数据类型 系列函数 By shawl.qiu
2007/03/06 Javascript
基于Jquery+Ajax+Json的高效分页实现代码
2011/10/29 Javascript
jQuery动画效果-slideUp slideDown上下滑动示例代码
2013/08/28 Javascript
Angularjs编写KindEditor,UEidtor,jQuery指令
2015/01/28 Javascript
angularJS结合canvas画图例子
2015/02/09 Javascript
JQuery实现带排序功能的权限选择实例
2015/05/18 Javascript
javascript实现确定和取消提示框效果
2015/07/10 Javascript
JS实现自动变化的导航菜单效果代码
2015/09/09 Javascript
Javascript打印局部页面实例
2016/06/21 Javascript
JavaScript中日期函数的相关操作知识
2016/08/03 Javascript
Three.js学习之Lamber材质和Phong材质
2016/08/04 Javascript
NodeJs搭建本地服务器之使用手机访问的实例讲解
2018/05/12 NodeJs
vue 使用 vue-pdf 实现pdf在线预览的示例代码
2020/04/26 Javascript
JavaScript实现像雪花一样的Hexaflake分形
2020/07/07 Javascript
uniapp实现可以左右滑动导航栏
2020/10/21 Javascript
[01:17:12]职来职往完美电竞专场
2014/09/18 DOTA
python爬虫入门教程--快速理解HTTP协议(一)
2017/05/25 Python
Python机器学习之决策树算法实例详解
2017/12/06 Python
Python基于plotly模块实现的画图操作示例
2019/01/23 Python
Numpy一维线性插值函数的用法
2020/04/22 Python
Python字符串对齐、删除字符串不需要的内容以及格式化打印字符
2021/01/23 Python
5分钟实现Canvas鼠标跟随动画背景
2019/11/18 HTML / CSS
世界上最大的乐谱选择:Sheet Music Plus
2020/01/18 全球购物
JRE、JDK、JVM之间的关系怎样
2012/05/16 面试题
先进党支部事迹材料
2014/01/13 职场文书
小学六年级学生评语
2014/04/22 职场文书
2014教师年度工作总结
2014/11/10 职场文书
2014年信访维稳工作总结
2014/12/08 职场文书
应聘教师自荐信
2015/03/26 职场文书
学习党史心得体会2016
2016/01/23 职场文书