React - ref、回调 ref 回调执行次数的问题、createRef 函数、事件处理

一、ref

1、字符串形式的 ref
html 复制代码
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>字符串形式的 ref</title>
    </head>

    <body>
        <div id="test"></div>
    </body>

    <script src="../js/react/react.development.js" type="text/javascript"></script>
    <script src="../js/react/react-dom.development.js" type="text/javascript"></script>
    <script src="../js/react/babel.min.js" type="text/javascript"></script>
    <script type="text/babel">
        class Demo extends React.Component {
            showData = () => {

                // 这里收集的是真实 DOM
                alert(this.refs.input1.value);
            };

            showData2 = () => {
                alert(this.refs.input2.value);
            };

            render() {
                return (
                    <div>
                        <input ref="input1" type="text" placeholder="点击按钮提示数据" />
                        &nbsp;
                        <button onClick={this.showData}>点击提示左侧的数据</button>&nbsp;
                        <input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
                    </div>
                );
            }
        }

        ReactDOM.render(<Demo />, document.getElementById("test"));
    </script>
</html>
2、回调函数形式的 ref
html 复制代码
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>回调函数形式的 ref</title>
    </head>

    <body>
        <div id="test"></div>
    </body>

    <script src="../js/react/react.development.js" type="text/javascript"></script>
    <script src="../js/react/react-dom.development.js" type="text/javascript"></script>
    <script src="../js/react/babel.min.js" type="text/javascript"></script>
    <script type="text/babel">
        class Demo extends React.Component {
            showData = () => {
                alert(this.input1.value);
            };

            showData2 = () => {
                alert(this.input2.value);
            };

            render() {
                return (
                    <div>
                        <input
                            ref={(currentNode) => {
                                this.input1 = currentNode;
                            }}
                            type="text"
                            placeholder="点击按钮提示数据"
                        />
                        &nbsp;
                        <button onClick={this.showData}>点击提示左侧的数据</button>&nbsp;
                        <input ref={(c) => (this.input2 = c)} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
                    </div>
                );
            }
        }

        ReactDOM.render(<Demo />, document.getElementById("test"));
    </script>
</html>

二、回调 ref 回调执行次数的问题

1、基本介绍
  1. 每次渲染时,内联回调都会被重新创建,类方法回调则不会被重新创建

  2. 先调用旧的 ref 回调,传入 null(清理),再调用新的 ref 回调,传入当前的 DOM 元素

阶段 类方法回调 内联回调
挂载 传入 DOM(1 次) 传入 DOM(1 次)
更新 不执行 先 null 后 DOM(2 次)
卸载 传入 null(1 次) 传入 null(1 次)
2、演示
html 复制代码
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>回调 ref 回调执行次数的问题</title>
	</head>

	<body>
		<div id="test"></div>
	</body>

	<script src="../js/react/react.development.js" type="text/javascript"></script>
	<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
	<script src="../js/react/babel.min.js" type="text/javascript"></script>
	<script type="text/babel">
		class Demo extends React.Component {
			state = {
				isHot: true,
			};

			changeWeather = () => {
				const { isHot } = this.state;
				this.setState({
					isHot: !isHot,
				});
			};

			showData = () => {
				alert(this.input1.value);
			};

			getInput2 = (currentNode) => {
				this.input2 = currentNode;
				console.log("#", currentNode);
			};

			showData2 = () => {
				alert(this.input2.value);
			};

			render() {
				const { isHot } = this.state;

				return (
					<div>
						<div>今天天气很{isHot ? "炎热" : "凉爽"}</div>
						<button onClick={this.changeWeather}>点我切换天气</button>
						<br />
						<input
							ref={(currentNode) => {
								this.input1 = currentNode;
								console.log("@", currentNode);
							}}
							type="text"
							placeholder="点击按钮提示数据"
						/>
						&nbsp;
						<button onClick={this.showData}>点击提示左侧的数据</button>&nbsp;
						<input ref={this.getInput2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
					</div>
				);
			}
		}

		ReactDOM.render(<Demo />, document.getElementById("test"));
	</script>
</html>

三、createRef 函数

1、基本介绍
  • React 的 createRef 函数在调用后返回一个容器,该容器可以存储被 ref 所标识的节点
2、演示
html 复制代码
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>createRef()</title>
	</head>

	<body>
		<div id="test"></div>
	</body>

	<script src="../js/react/react.development.js" type="text/javascript"></script>
	<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
	<script src="../js/react/babel.min.js" type="text/javascript"></script>
	<script type="text/babel">
		class Demo extends React.Component {
			input1 = React.createRef();
			input2 = React.createRef();

			showData = () => {
				console.log(this.input1);
				alert(this.input1.current.value);
			};

			showData2 = () => {
				console.log(this.input2);
				alert(this.input2.current.value);
			};

			render() {
				return (
					<div>
						<input ref={this.input1} type="text" placeholder="点击按钮提示数据" />
						&nbsp;
						<button onClick={this.showData}>点击提示左侧的数据</button>&nbsp;
						<input ref={this.input2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
					</div>
				);
			}
		}

		ReactDOM.render(<Demo />, document.getElementById("test"));
	</script>
</html>

四、事件处理

1、基本介绍
  1. 通过 onXxx 属性指定事件处理函数

    1. 原生:onclick,React:onClick

    2. React 使用的是自定义(合成)事件,不是原生的 DOM 事件(为了更好的兼容性)

    3. React 中的事件是通过事件委托的方式处理的(委托给组件最外层的元素,为了高效)

    4. 可以通过 event.target 得到发生事件的原生 DOM 对象

  2. 发生事件的元素正好是要操作的元素,就可以省略 ref,不要过度使用 ref

2、演示
html 复制代码
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>事件处理</title>
	</head>

	<body>
		<div id="test"></div>
	</body>

	<script src="../js/react/react.development.js" type="text/javascript"></script>
	<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
	<script src="../js/react/babel.min.js" type="text/javascript"></script>
	<script type="text/babel">
		class Demo extends React.Component {
			input1 = React.createRef();
			input2 = React.createRef();

			showData = () => {
				alert(this.input1.current.value);
			};

			showData2 = (event) => {
				alert(event.target.value);
			};

			render() {
				return (
					<div>
						<input ref={this.input1} type="text" placeholder="点击按钮提示数据" />
						&nbsp;
						<button onClick={this.showData}>点击提示左侧的数据</button>&nbsp;
						<input ref={this.input2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
					</div>
				);
			}
		}

		ReactDOM.render(<Demo />, document.getElementById("test"));
	</script>
</html>
相关推荐
来碗疙瘩汤2 小时前
深入解析 Vue 包:`vue` 究竟导出了什么?
前端
我命由我123452 小时前
React - 收集表单元素、收集表单元素优化、生命周期(旧)、生命周期(新)
前端·javascript·react.js·前端框架·html·html5·js
SuperEugene2 小时前
Monorepo + pnpm workspace 落地实操:Vue 中后台多项目 / 组件库 / 公共包管理|Vue 工程化篇
前端·javascript·vue.js·pnpm·vite·monorepo
We་ct2 小时前
JSX & ReactElement 核心解析
前端·react.js·面试·架构·前端框架·reactjs·个人开发
白中白121382 小时前
杂七杂八补充系列
开发语言·前端·javascript
Xingxing?!2 小时前
Vue2 微信小程序:页面间传递数组
前端·vue.js·uni-app
肉肉不吃 肉2 小时前
代理服务的原理,及Vite 中具体实现方法
前端·vue.js
前端小D2 小时前
作用域/闭包
前端·javascript
前端 贾公子2 小时前
@uni-helper 社区:让 uni-app 拥抱 ESM 时代
开发语言·前端·javascript