位置: IT常识 - 正文

React props全面详细解析

编辑:rootadmin
props 是 React 组件通信最重要的手段,它在 React 的世界中充当的角色是十分重要的。学好 props 可以使组件间通信更加灵活,同时文中会介绍一些 props 的操作技巧,和学会如何编写嵌套组件 目录

推荐整理分享React props全面详细解析,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

一、Props 是什么二、props children模式1. props 插槽组件2. render props模式3. render props模式三、进阶实践一、Props 是什么

先来看一个 demo :

function Chidren(){return <div> 我是子组件 </div>}/* props 接受处理 */function Father(props) {const { children , mes , renderName , say ,Component } = propsconst renderFunction = children[0]const renderComponent = children[1]/* 对于子组件,不同的props是怎么被处理 */return (<div>{ renderFunction() }{ mes }{ renderName() }{ renderComponent }<Component /><button onClick={ () => say() } > 触发更改 </button></div> )}/* props 定义绑定 */class App extends React.Component{state={mes: "hello,React"}node = nullsay= () => this.setState({ mes:'let us learn React!' })render(){return <div><Fathermes={this.state.mes} // ① props 作为一个渲染数据源say={ this.say } // ② props 作为一个回调函数 callbackComponent={ Chidren } // ③ props 作为一个组件renderName={ ()=><div> my name is YinJie </div> } // ④ props 作为渲染函数>{ ()=> <div>hello,world</div> } { /* ⑤render props */ }<Chidren /> { /* ⑥render component */ }</Father></div>}}

我们看一下输出结果:

当点击触发更改时就能够调用回调更改数据源:

所以 props 可以是:

① props 作为一个子组件渲染数据源。

② props 作为一个通知父组件的回调函数。

③ props 作为一个单纯的组件传递。

④ props 作为渲染函数。

⑤ render props , 和④的区别是放在了 children 属性上。

⑥ render component 插槽组件。

二、props children模式

我们先来看看 prop + children 的几个基本情况:

1. props 插槽组件<Container><Children></Container>

上述可以在 Container 组件中,通过 props.children 属性访问到 Children 组件,为 React element 对象。

作用:

可以根据需要控制 Children 是否渲染。像上一节所说的, Container 可以用 React.cloneElement 强化 props (混入新的 props ),或者修改 Children 的子元素。

举一个用React.cloneElement 强化 props 的例子,多用于编写组件时对子组件混入新的 props,下面我们要做一个导航组件,我们希望它的结构如下:

<Menu><MenuItem >active</MenuItem><MenuItem>disabled</MenuItem><MenuItem >xyz</MenuItem></Menu>

我们想给每个 MenuItem 子组件都添加 index 属性,这个事情不应该让用户手动添加,最好是可以在 Menu 组件中自动为每个 MenuItem 子组件添加上,并且 Menu 组件还应该判断子组件的类型,如果子组件的类型不是 MenuItem 组件就报错。

React props全面详细解析

Menu.tsx:

const Menu: React.FC<MenuProps> = (props) => {// ... 一些操作const renderChildren = () => { // 让子级的children都是 menuItem,有不是的就报错return React.Children.map(children, (child, index) => {const childElement = child as React.FunctionComponentElement<MenuItemProps>const { displayName } = childElement.typeif(displayName === 'MenuItem' || displayName === "SubMenu") {return React.cloneElement(childElement, { index: index.toString() })} else {console.error('warning: Menu has a child whitch is not a MenuItem')}})}return (<ul className={classes} style={style} data-testid="test-menu"><MenuContext.Provider value={passedContext}>{renderChildren()}</MenuContext.Provider></ul>)}

在 Menu 组件中我们通过 React.children.map 来循环子组件,通过 child.type 可以获取到每个子组件的 displayName 静态属性,这个在子组件中有定义:

通过子组件的 displayName 来判断是否是我们需要的 MenuItem,如果是的话就调用 React.cloneElement 来为子组件添加 index 属性。

2. render props模式<Container>{ (ContainerProps)=> <Children {...ContainerProps} /> }</Container>

这种情况,在 Container 中, props.children 属性访问到是函数,并不是 React element 对象,我们应该调用这个函数:

function Container(props) {const ContainerProps = {name: 'alien',mes:'let us learn react'}return props.children(ContainerProps)}

这种方式作用是:

1 根据需要控制 Children 渲染与否。

2 可以将需要传给 Children 的 props 直接通过函数参数的方式传递给执行函数 children 。

3. render props模式

如果 Container 的 Children 既有函数也有组件,这种情况应该怎么处理呢?

<Container><Children />{ (ContainerProps)=> <Children {...ContainerProps} name={'haha'} /> }</Container>const Children = (props)=> (<div><div>hello, my name is { props.name } </div><div> { props.mes } </div></div>)function Container(props) {const ContainerProps = {name: 'alien',mes:'let us learn react'}return props.children.map(item=>{if(React.isValidElement(item)){ // 判断是 react elment 混入 propsreturn React.cloneElement(item,{ ...ContainerProps },item.props.children)}else if(typeof item === 'function'){return item(ContainerProps)}else return null})}const Index = ()=>{return <Container><Children />{ (ContainerProps)=> <Children {...ContainerProps} name={'haha'} /> }</Container>}

这种情况需要先遍历 children ,判断 children 元素类型:

针对 element 节点,通过 cloneElement 混入 props ;针对函数,直接传递参数,执行函数。三、进阶实践

实现一个简单的<Form> <FormItem>嵌套组件

接下来到实践环节了。需要编写一个实践 demo ,用于表单状态管理的<Form>和<FormItem>组件

<Form>用于管理表单状态;<FormItem>用于管理<Input>输入框组件。,

编写的组件能够实现的功能是:

①Form组件可以被 ref 获取实例。然后可以调用实例方法submitForm获取表单内容,用于提交表单,resetForm方法用于重置表单。

②Form组件自动过滤掉除了FormItem之外的其他React元素

③FormItem中 name 属性作为表单提交时候的 key ,还有展示的 label 。

④FormItem可以自动收集<Input/>表单的值。

App.js:

import React, { useState, useRef } from "react";import Form from './Form'import FormItem from './FormItem'import Input from './Input'function App () {const form = useRef(null)const submit =()=>{/* 表单提交 */form.current.submitForm((formValue)=>{ // 调用 form 中的submitForm方法console.log(formValue)})}const reset = ()=>{/* 表单重置 */form.current.resetForm() //调用 form 中的 resetForm 方法}return <div className='box' ><Form ref={ form } ><FormItem name="name" label="我是" ><Input /></FormItem><FormItem name="mes" label="我想对大家说" ><Input /></FormItem><FormItem name="lees" label="ttt" ><Input /></FormItem></Form><div className="btns" ><button className="searchbtn" onClick={ submit } >提交</button><button className="concellbtn" onClick={ reset } >重置</button></div></div>}export default App

Form.js:

class Form extends React.Component{state={formData:{}}/* 用于提交表单数据 */submitForm=(cb)=>{cb({ ...this.state.formData })}/* 获取重置表单数据 */resetForm=()=>{const { formData } = this.stateObject.keys(formData).forEach(item=>{formData[item] = ''})this.setState({formData})}/* 设置表单数据层 */setValue=(name,value)=>{this.setState({formData:{...this.state.formData,[name]:value}})}render(){const { children } = this.propsconst renderChildren = []React.Children.forEach(children,(child)=>{if(child.type.displayName === 'formItem'){const { name } = child.props/* 克隆`FormItem`节点,混入改变表单单元项的方法 */const Children = React.cloneElement(child,{key:name , /* 加入key 提升渲染效果 */handleChange:this.setValue , /* 用于改变 value */value:this.state.formData[name] || '' /* value 值 */},child.props.children)renderChildren.push(Children)}})return renderChildren}}/* 增加组件类型type */Form.displayName = 'form'

设计思想:

首先考虑到<Form>在不使用forwardRef前提下,最好是类组件,因为只有类组件才能获取实例。创建一个 state 下的 formData属性,用于收集表单状态。要封装重置表单,提交表单,改变表单单元项的方法。要过滤掉除了FormItem元素之外的其他元素,那么怎么样知道它是不是FormItem,这里教大家一种方法,可以给函数组件或者类组件绑定静态属性来证明它的身份,然后在遍历 props.children 的时候就可以在 React element 的 type 属性(类或函数组件本身)上,验证这个身份,在这个 demo 项目,给函数绑定的 displayName 属性,证明组件身份。要克隆FormItem节点,将改变表单单元项的方法 handleChange 和表单的值 value 混入 props 中。

FormItem.js:

function FormItem(props){const { children , name , handleChange , value , label } = propsconst onChange = (value) => {/* 通知上一次value 已经改变 */handleChange(name,value)}return <div className='form' ><span className="label" >{ label }:</span>{React.isValidElement(children) && children.type.displayName === 'input'? React.cloneElement(children,{ onChange , value }): null}</div>}FormItem.displayName = 'formItem'

设计思想:

FormItem一定要绑定 displayName 属性,用于让<Form>识别<FormItem />
本文链接地址:https://www.jiuchutong.com/zhishi/311680.html 转载请保留说明!

上一篇:Java 中的Double Check Lock(转)(java中double是什么数据类型)

下一篇:织梦ckeditor编辑器升级为ckeditor4-word图片自动上传mp4播放批量图片上传(织梦怎样实现文件上传)

  • 苹果手机怎样把健康码添加到桌面上(苹果手机怎样把照片拼图合成)

    苹果手机怎样把健康码添加到桌面上(苹果手机怎样把照片拼图合成)

  • 苹果x原彩显示什么意思(苹果x原彩显示不见了)

    苹果x原彩显示什么意思(苹果x原彩显示不见了)

  • 微信发朋友圈怎么@别人(微信发朋友圈怎么定位到外地的位置)

    微信发朋友圈怎么@别人(微信发朋友圈怎么定位到外地的位置)

  • 苹果a13比a12强多少(苹果a13对比)

    苹果a13比a12强多少(苹果a13对比)

  • 买家被卖家投诉会封号吗(买家被卖家投诉会怎样)

    买家被卖家投诉会封号吗(买家被卖家投诉会怎样)

  • qq怎么看密友值(qq怎么看密友值,对方知道吗)

    qq怎么看密友值(qq怎么看密友值,对方知道吗)

  • 抖音直播显示本场点赞是什么意思(抖音直播显示本人怎么弄)

    抖音直播显示本场点赞是什么意思(抖音直播显示本人怎么弄)

  • 微信视频像素怎么调整(微信视频像素怎么办)

    微信视频像素怎么调整(微信视频像素怎么办)

  • 韩剧tv怎么投屏到电视(韩剧TV怎么投屏到电视)

    韩剧tv怎么投屏到电视(韩剧TV怎么投屏到电视)

  • 苹果手机怎么设置一个圈(苹果手机怎么设置密码锁屏)

    苹果手机怎么设置一个圈(苹果手机怎么设置密码锁屏)

  • mp3视频格式是什么(mp3视频格式是什么怎么下载)

    mp3视频格式是什么(mp3视频格式是什么怎么下载)

  • 华为手机屏幕黑线修复(华为手机屏幕黑了怎么调回去)

    华为手机屏幕黑线修复(华为手机屏幕黑了怎么调回去)

  • wps文件夹怎么发给别人(wps文件夹怎么发到钉钉)

    wps文件夹怎么发给别人(wps文件夹怎么发到钉钉)

  • qq显示忙碌还能聊天吗(qq显示忙碌是啥意思)

    qq显示忙碌还能聊天吗(qq显示忙碌是啥意思)

  • 手机里的大文件是什么(如何找到手机里的大文件)

    手机里的大文件是什么(如何找到手机里的大文件)

  • 怎么开启笔记本电脑的无线功能(怎么开启笔记本无线网络功能)

    怎么开启笔记本电脑的无线功能(怎么开启笔记本无线网络功能)

  • 苹果8p外屏碎要不要换(8p外屏碎了还能卖多少钱)

    苹果8p外屏碎要不要换(8p外屏碎了还能卖多少钱)

  • 手机录屏可以录声音吗(手机录屏可以录音吗)

    手机录屏可以录声音吗(手机录屏可以录音吗)

  • 乐视手机备份功能在哪(乐视手机有云备份吗)

    乐视手机备份功能在哪(乐视手机有云备份吗)

  • 爱奇艺后台设置在哪里

    爱奇艺后台设置在哪里

  • 印度没有总统吗(印度为啥没有总统)

    印度没有总统吗(印度为啥没有总统)

  • 携程10元套餐怎么取消(携程10元套餐怎么退)

    携程10元套餐怎么取消(携程10元套餐怎么退)

  • iqooneo855有nfc功能吗(iqooneo855版nfc)

    iqooneo855有nfc功能吗(iqooneo855版nfc)

  • 1416是ipad几(ipad型号1416是几代)

    1416是ipad几(ipad型号1416是几代)

  • 转转如何退货(转转如何退货寄给卖家)

    转转如何退货(转转如何退货寄给卖家)

  • 图片已过期或被清理是对方删了吗(图片已过期)

    图片已过期或被清理是对方删了吗(图片已过期)

  • 苹果xs什么处理器(苹果x什么处理器)

    苹果xs什么处理器(苹果x什么处理器)

  • 怎样监听别人的手机(怎样监听别人的手机通话微信)

    怎样监听别人的手机(怎样监听别人的手机通话微信)

  • 用YOLOv8推荐的Roboflow工具来训练自己的数据集(yolo v5 github)

    用YOLOv8推荐的Roboflow工具来训练自己的数据集(yolo v5 github)

  • 电脑学习网2022年如何申请Paypal的API接口申请,傻瓜试教程-电脑学习网(网上学电脑)

    电脑学习网2022年如何申请Paypal的API接口申请,傻瓜试教程-电脑学习网(网上学电脑)

  • 买一赠一的税务处理
  • 财务软件应交增值税明细科目
  • 公司购车购置税有优惠吗
  • 收到存款利息怎么写分录
  • 对公账户汇款方式
  • 贷款还款利息怎么还
  • 一人有限公司年度审计报告
  • 出口专用发票应在哪里开
  • 当月进项税额大于销项税额
  • 产权转移数据印花税按次申报?
  • 买东西几块钱忘付了怎么办
  • 年报怎么看
  • 分摊长期待摊费用的会计分录
  • 公司客车高速费如何抵扣进项税?
  • 其他综合收益影响净利润吗
  • 购买债券发生的交易费用计入哪个科目
  • 收到上月发票怎么写分录
  • 自然人个人能否纳税
  • 计提利息收入怎么做账
  • mac文件权限限制怎么解决
  • 退付手续费怎么操作
  • 年薪制职工薪酬计算方法
  • 鸿蒙系统蓝牙耳机声音小怎么办
  • 电脑自动更新系统
  • 缴纳公积金个人部分会计分录
  • 苹果官网
  • wordpress邮箱怎么配置
  • 工程审计需要什么条件
  • wordpress怎么搜索域名
  • 未注销的坏账可以转出吗
  • php递归遍历文件夹
  • 运输取得的收入
  • 应收挂账太久有什么税务风险
  • nginx反向代理详解
  • thinkphp获取get传值
  • 微信 php sdk
  • 跨地区经营建筑企业预缴增值税
  • vue操作excel
  • erp面试题目100及最佳答案
  • ls -lh命令
  • 预付的购货款计入什么科目
  • 公司买办公用品是谁的工作
  • 花生油代加工厂
  • 生产企业成本会计做账流程
  • 增值税免税收入账务处理
  • 不动产简易征收增值税发票 可以抵扣
  • vue打包找不到文件
  • 月度合并报表与年度合并区别
  • 其他资本公积可以冲减吗
  • 基本户和一般户可以互相转账吗
  • SQL SERVER 2000通讯管道后复用劫持
  • 公对私转账交税
  • 政府扶持国有企业
  • 个体工商户定期定额怎么报税
  • 营改增后所得税怎么计算
  • 一般纳税人税种核定表
  • 暂不认证通知单 不在认证范围内
  • 核定征收需要什么资料
  • 租入办公楼装修费按几年摊销
  • 商业企业销售摩托车需不需要征收消费税
  • 伤病假条
  • 任务管理器已被管理员禁用怎么办
  • xp电脑启动项怎么设置启动项
  • windows7的关闭方法
  • linux安装xen
  • bat脚本判断
  • nodejs writefile
  • node.js javascript
  • javascript ()
  • centos上安装邮件服务器
  • bat批处理if命令
  • android使用so
  • javascript 自动执行
  • android程序崩溃会被重启
  • 国家税务总局财政部公告2023年第11号
  • 残疾人保障金如何填报
  • 农民专业合作社法
  • 烟叶税比例
  • 18个税种征税范围
  • 告知承诺和非告知承诺
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设