再仔细读读react18官方文档吧 20220530

章节回顾:



表单

受控组件

什么是"受控组件?"

官方文档解释:

在这里插入图片描述

简单概括为:

表单值的获取和更新操作,交由react中的state来管理

比如:

<input type="text" />

<textarea></textarea>

<select></select>

使用示例:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<div id="root"></div>
	<!-- 开发模式下用development版本 -->
	<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
	<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
	<script type="text/babel">
		const {useState} = React
		const {createRoot} = ReactDOM
		function Inp() {
			const [val, setVal] = useState('')
			const handleChange = e => {
				let v = e.target.value
				setVal(v)
			}
			const handleSubmit = e => {
				alert('提交的内容:' + val)
				setVal('')
				e.preventDefault()
			}
			return <form onSubmit={handleSubmit}>
				<input type="text" value={val} onChange={handleChange} />
				<br />
				<input type="submit" value="提交" />
			</form>
		}
		const wrap = document.querySelector('#root')
		const root = createRoot(wrap)
		root.render(<Inp />)
	</script>
</body>
</html>

非受控组件

什么是"非受控组件"?

用ref从DOM中获取表单数据,也就是要“直接操作DOM”

比如

<input type="file" />

获取用户上传照片详情示例:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<div id="root"></div>
	<!-- 开发模式下用development版本 -->
	<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
	<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
	<script type="text/babel">
		const {useRef} = React
		const {createRoot} = ReactDOM
		function Inp() {
			const inp = useRef(null)
			const handleSubmit = e => {
				// 上传的文件内容
				console.log(inp.current.files)
				e.preventDefault()
			}
			return <form onSubmit={handleSubmit}>
				<input type="file" ref={inp} />
				<br />
				<input type="submit" value="提交" />
			</form>
		}
		const wrap = document.querySelector('#root')
		const root = createRoot(wrap)
		root.render(<Inp />)
	</script>
</body>
</html>

上传图片后,点击提交,可以看到用户上传的图片信息:

在这里插入图片描述


总结一下:

受控组件就是把表单的值和操作都交给state来统一管理,

非受控组件就是直接操作DOM,用ref来管理。

二者都是操控表单组件的方式,很多情况下,

一个表单,既可以用受控组件方式处理,又可以用非受控组件方式处理。


value or defaultValue ?

二者都可以在初始状态给表单设置默认值/初始值。

但是,有一点区别。

在表单中,如果你只需要给表单设置一个默认值,

而不去管他后续的更新,这时候就用defaultValue。

不然就会报错:

在这里插入图片描述

也就是说,你不用去获取这个value来更新表单的值的时候,就用defaultValue。

具体可以看下面状态提升中的示例。


状态提升

什么是状态提升?

官方文档给出的解释:

在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。
这就是所谓的“状态提升”。

换句话说,就是:

子传父。

把一个子组件的值传给父组件,

然后通过父组件,把这个值再传给其他子组件使用。

子传父

子传父流程

  • 父组件创建一个需要传参的函数
  • 哪个子组件要做状态提升,即子组件的值要传给父组件,就把该函数名先传给该子组件
  • 该子组件通过props接收到该函数,要传值给父组件时,调用该函数,并把值作为参数传入
  • 父组件通过该函数的参数,获取子组件传来的值
  • 子传父完成

状态提升完整示例:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<div id="root"></div>
	<!-- 开发模式下用development版本 -->
	<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
	<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
	<script type="text/babel">
		const {useState} = React
		const {createRoot} = ReactDOM
		function Child1(props) {
			const {getValue} = props
			const [val1, setVal1] = useState('')
			const handleChange1 = e => {
				let v = e.target.value
				setVal1(v)
				// 3. 值变更时,调用函数,传入参数v
				getValue(v)
			}
			return <input type="text" value={val1} onChange={handleChange1} />
		}
		function Child2(props) {
			// 6. 获取到父组件传来的值
			const {f} = props
			// 7. 把值交给表单。整个状态提升完成。
			return <input type="text" defaultValue={f} />
		}
		function Father(props) {
			const [f, setF] = useState('')
			// 1. 创建一个需要传参的函数,用于获取子组件的值
			const getValue = (v) => {
				// 4. 获取到子组件传来的值,更新该值
				setF(v)
			}
			return <div>
				// 2. 把函数传给子组件
				input1: <Child1 getValue={getValue} /><br />
				<br />
				// 5. 把从子组件1获取到的值,传给子组件2
				input2: <Child2 f={f} />
			</div>
		}
		const wrap = document.querySelector('#root')
		const root = createRoot(wrap)
		root.render(<Father />)
	</script>
</body>
</html>

组合 vs 继承

在父组件中,常常包含一些拥有未知内容的子组件,

此时,就需要一些特殊方法来渲染它们。

这些特殊方法,就有组合和继承。 先来说说组合。


组合

props.children

props.children表示在父组件中的子组件标签中所包含的所有内容

示例:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<div id="root"></div>
	<!-- 开发模式下用development版本 -->
	<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
	<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
	<script type="text/babel">
		const {createRoot} = ReactDOM
		function Child(props) {
			console.log('props: ', props)
			return <div>
				{props.children}
			</div>
		}
		function Father() {
			return <div>
				<Child color="pink">
					<h3>
						hello react !	
					</h3>
					<p>test here ~</p>
				</Child>
			</div>
		}
		const wrap = document.querySelector('#root')
		const root = createRoot(wrap)
		root.render(<Father />)
	</script>
</body>
</html>

来看下子组件中打印出来的props:

在这里插入图片描述

这个props包含了子组件标签内联的color

同时还有一个children属性,包含了标签中的DOM元素。

props.children中进行渲染,可以在页面中看到渲染的页面结果。

在这里插入图片描述


slot插槽

在vue中,有slot插槽概念。但是在react中,没有这一概念。这里的slot,只是借助了vue中的说法。

react中的"slot",表示的是,把组件当作prop传递给子组件

示例:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<div id="root"></div>
	<!-- 开发模式下用development版本 -->
	<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
	<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
	<script type="text/babel">
		const {createRoot} = ReactDOM
		function Com1() {
			return <h3>
				hello react !
			</h3>
		}
		function Com2() {
			return <p>test here ~</p>
		}
		function Child(props) {
			return <div>
				<div className="left">{props.left}</div>
				<div className="rig">{props.rig}</div>
			</div>
		}
		function Father() {
			return <div>
				{/*把组件当作prop传递给子组件*/}
				<Child left={<Com1 />} rig={<Com2 />} />
			</div>
		}
		const wrap = document.querySelector('#root')
		const root = createRoot(wrap)
		root.render(<Father />)
	</script>
</body>
</html>

继承

在这里插入图片描述

话不多说, 官方文档就给提供了这句话,应该就明白啥意思了。

但是,有些公司老项目,还是用到了继承。

举个例子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<div id="root"></div>
	<!-- 开发模式下用development版本 -->
	<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
	<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
	<script type="text/babel">
		const {createRoot} = ReactDOM
		class Father extends React.Component {
			render() {
				return <div>
					hello react !	
				</div>
			}
		}
		class Child extends Father {}
		const wrap = document.querySelector('#root')
		const root = createRoot(wrap)
		root.render(<Child />)
	</script>
</body>
</html>

在实际开发中,如果遇到,至少可以看懂。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值