最易懂-react18入门系列二

111 阅读6分钟

摘要

本篇主要是react基础篇。

  • 受控表单绑定[表单双向绑定的处理]
  • 获取dom方式
  • 组件通信
    • 父传子-props
    • 子传父-调方法
    • 兄弟之间- 先子传父,再父传子
    • 跨层传递-context

受控表单绑定

也就是vue里对应的的一个概念:表单数据的双向绑定。

概念: 使用React组件的状态(useState) 控制 表单的状态。

这里有2个状态值,一个是react内部的状态值,一个是表单用户录入的数据值。

双向:

  1. React[state] ---> [value] 把state值绑定到input的value上

  2. React[state] <--- [value] 把input用户输入的值告知(set)给React的state

具体怎么实现呢:

分2步:

  1. 准备一个React状态值
const [value,setValue] = useState('')
  1. 通过value属性绑定状态,通过onChange属性绑定状态同步的函数

双向全流程体现在2条线:

  1. value = {value},把state值绑定到input的value上

  2. setValue(e.target.value),把input用户输入的值告知(set)给React的state

<input type="text" value={value} onChange={(e)=> setValue(e.target.value)}

获取dom元素

通过useRef钩子函数。分2步:

  1. 使用useRef 创建ref对象,并绑定到dom标签身上。
const inputRef = useRef(null)

<input type="text" ref={inputRef}/>
  1. 在Dom可用时,通过 inputRef.current 拿到DOM对象。
console.dir(inputRef.current)
//ps:dir语句打印的是对象的所有属性和方法

注意: 这个 Dom可用时 的理解,是当前组件渲染完毕,也就是dom生成之后。比如:点击事件。这个时候肯定是渲染完了。

组件通信

概念:组件之间的数据传递。根据组件嵌套关系不同,通信方式也各不相同。

父传子

实现步骤:

  1. 父组件传递数据,在子组件标签上绑定一个属性。[发生在父组件中,子组件标签身上]

  2. 子组件接收数据,子组件通过props参数接收数据。[发生在子组件中 ]

通过props

代码实现:

一个简单的无通信的父子组件嵌套

function Father(){
	return(
		<div>
			<Son/>
		</div>
	)
}

function Son(){
	return <div> I am son </div>
}

此时,如果想把 Father里的一个数据 version 传递给Son。

function Father(){

	let ver = '1.1.0'

	return(
		<div>
			<Son version={ver}/>//1. 传递处,子标签身上自定义一个属性version.
		</div>
	)
}

function Son(props){//2. 接收处,加一入参props来收数据,具体属性名和定义处保持一致即可。
	return <div> I am son,版本 {props.version} </div>
}

props可传递的数据类型

react里props非常灵活,可以传递任意类型:数字、字符串、布尔值、对象、数组、函数、jsx(dom片段)

function Father(){

	let ver = '1.1.0'

	return(
		<div>
			<Son version={ver} 
			age={20} 
			isFlag={false} 
			arrList={['数学','语文']} 
			obj={{key1:val1}}
			cb={()=>console.log(1)}
			jsx={<div>I am dom</div>}
			/>//1. 传递处,子标签身上自定义
		</div>
	)
}

function Son(props){//2. 接收处,加一入参props来收数据,具体属性名和定义处保持一致即可。
	console.log(props)
	return <div> {props.version} </div>
}

props是只读对象

子组件里是不可以对props进行修改的,它是父组件的数据,所以只有父组件有权利改。

遵循 谁的数据,谁有权更改!

特殊的props-children

什么场景会用到呢?

当我们把内容嵌套在子组件标签中时,父组件会自动在名为children的prop属性中接收该内容。

function Father(){
	return(
		<div>
			<Son> <span> 我是嵌套到自定义标签Son里的子标签 </span></Son>
		</div>
	)
}

function Son(props){
	return <div> I am son {props.children}</div>
}

也就是说: 自定义标签里写东西,也是可以识别的,react把它识别到一个叫children的属性里了。

子传父

核心: 1、父通过props把一个自己的函数传递给子,2、然后在子中调用父组件中的函数并传递参数。

import {useState} from 'react'

function Father(){

	const [msg,setMsg] = useState('')

	const getMsg = (msg)=>{
		setMsg(msg)
	}

	return(
		<div>
			<Son onGetMsg={getMsg}/>
			来自son传递来的消息:{msg}
		</div>
	)
}

function Son(props){
	const msg = '我是子里要传给父的数据源'

	return <button onClick={()=> props.onGetMsg(msg)}>send</button>
}

兄弟组件传值

核心:将子传父,父传子 进行组合。也就是 利用 "状态提升" 机制!

父组件:App,子组件1:A ,子组件2:B

如果想实现A的值传递给B,我们可以先:A->App ,然后再 App->B

传值前,3个组件代码如下:

A:

function A(){
	const msg = '我是要传递的源数据'

	return(
		<div>
			我是A组件
			<button>send</button>
		</div>
	)
}

B:

function B(){

	return(
		<div>
			我是B组件
		</div>
	)
}

App:

function App(){

	return(
		<div>
			我是App组件
			<A></A>
			<B></B>
		</div>
	)
}

传值处理改造:

A:

function A(props){//2:
	const msg = '我是要传递的源数据'

	return(
		<div>
			我是A组件
			<button onClick={()=>props.onGetMsg(msg)}>send</button>//2:
		</div>
	)
}

B:

function B({msg}){//解构//4:

	return(
		<div>
			我是B组件
			传来的值:{msg}//4:
		</div>
	)
}

App:

function App(){
	// 这里用useState包裹成状态量,就是为了下游的B里具有响应性,A里的值发生变化,B中视图也能同步更新!
	const [msg,setMsg] = useState('')//1:
	const getMsg = (msg)=>{//1:
		setMsg(msg)
	}

	return(
		<div>
			我是App组件
			<A onGetMsg={getMsg}></A>//1:
			<B msg={msg}></B>//3:
		</div>
	)
}

1: 在父组件里,通过给A组件灌入一个props:onGetMsg 属性把 方法getMsg传进去。 2: 在A组件里,我们要用props参数接收 下发给我的方法属性onGetMsg,然后在触发角绑定方法并调用,同时把要传递的msg作为实参传递过去。 3: 在父组件里,已经拿到A传递的msg后,响应式状态量msg有值后,可以通过给B组件灌入一个props:msg 属性把 值传进去。 4: 在B组件里,我们要用props参数接收 下发给我的属性msg,然后在页面里使用,显示出来。

至此,一个完整的传递过程完成了。代码里按照处理顺序标记了序号1/2/3/4

跨层组件传值

可能是爷孙,只要是层级嵌套关系的就可以使用。

主要3步:

1. 使用 createContext 方法创建一个上下文对象Ctx
2. 在顶层组件中通过 Ctx.Provider组件 提供数据
3. 在底层组件中通过useContext钩子函数获取并使用数据

案例:

App > A > B, App里嵌套A,A里嵌套B,想把App里的数据msg传递给B.

传递前组件代码:

function A(){
	return(
		<div>
			我是A组件
			<B/>
		</div>
	)
}

function B(){
	return(
		<div>
			我是B组件
		</div>
	)
}

function App(){

	const msg = '我是要传递的源数据'

	return(
		<div>
			我是App组件
			<A></A>
		</div>
	)
}

传值处理改造:

import {createContext} from 'react'

const MsgContext = createContext()//1: 创建Ctx上下文,一般命名:大驼峰,消息名+Context组合

function A(){
	return(
		<div>
			我是A组件
			<B/>
		</div>
	)
}

function B(){
	const msg = useContext(MsgContext)//3:在底层消费数据组件里利用hooks函数useContext进行接收数据(之前创建的Ctx-> MsgContext)

	return(
		<div>
			我是B组件
			使用接收到的数据:{msg}
			使用接收到的数据:{msg}
		</div>
	)
}

function App(){

	const msg = '我是要传递的源数据'

	return(
		<div>
			//2.在底层传送数据组件里,使用Ctx.Provider组件标签包裹住要所有子节点,尤其是A(因为A里嵌套B),同时通过value属性把值传入。
			<MsgContext.Provider value={msg}>
				我是App组件
				<A></A>
			</MsgContext.Provider>
		</div>
	)
}