1 概述
组件内的标签通过定义ref属性来标识自己。
做一个小实例,如下图所示:

两个输入框,第一个输入框输入内容,点击后面按钮,弹窗显示输入内容;第二输入框,失去焦点弹窗显示输入内容。
这里我需要获取页面DOM input,进而获取输入框内容,下面我来看看在react怎么怎么做。
1 字符串形式refs
示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>0801_字符串形式refs</title>
</head>
<body>
<div id="test1"></div>
<!-- react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Person extends React.Component {
render() {
return (
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点击显示数据</button><br/>
<input ref="input2" type="text" placeholder="失去焦点提示数据" onBlur={this.showData1}/>
</div>
)
}
// 点击提示数据
showData = () => {
let {input1} = this.refs
alert(input1.value)
}
// 失去焦点提示数据
showData1 = () => {
let {input2} = this.refs
alert(input2.value)
}
}
// 2.渲染虚拟DOM到页面
ReactDOM.render(<Person/>, document.getElementById('test1'))
</script>
</body>
</html>
字符串形式refs格式:
// refs 声明
<标签 ref="xxx" />
// refs 使用
this.refs.xxx
this.refs.xxx表示的不是虚拟DO M,而是虚拟DOM转化后的真实DOM。
2 回调形式refs
2.1 基本使用
上述字符串形式refs官网不建议使用,它存在一些问题,比如效率问题等,在后续更新中可能废弃。
react还提供一种回调形式的refs,以上面实例为例,使用回调形式ref,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>0802_回调形式refs</title>
</head>
<body>
<div id="test1"></div>
<!-- react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Person extends React.Component {
// 对标签属性类型、必要性做限制
render() {
return (
<div>
<input ref={c => this.input1 = c} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点击显示数据</button><br/>
<input ref={c => this.input2 = c} type="text" placeholder="失去焦点提示数据" onBlur={this.showData1}/>
</div>
)
}
// 点击提示数据
showData = () => {
let {input1} = this
alert(input1.value)
}
// 失去焦点提示数据
showData1 = () => {
let {input2} = this
alert(input2.value)
}
}
// 2.渲染虚拟DOM到页面
ReactDOM.render(<Person/>, document.getElementById('test1'))
</script>
</body>
</html>
回调形式ref格式:
ref={结点参数 => {this.xxx=结点参数}} // 把传递的参数结点挂载在组件实例上
2.2 回调refs调用次数问题
官网说明:
If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the ref callback as a bound method on the class, but note that it shouldn’t matter in most cases.
如果回调函数以内联函数定义,在更新的时候会被调用2次,第一次传递的结点为null,第二次才传递DOM元素。因为每次render都会创建新的函数实例,react需要清理旧的ref,设置新的ref。如果要使用回调形式ref,需要把ref回调定义在组件实例上。
示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>0803_回调refs执行次数问题</title>
</head>
<body>
<div id="test1"></div>
<!-- react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Person extends React.Component {
// 对标签属性类型、必要性做限制
state = {
isHot: true
}
render() {
return (
<div>
<h2>今天天气很{this.state.isHot?'炎热': '凉爽'}</h2>
<button onClick={this.changeWeather}>切换天气</button><br/>
{/*<input ref={(c) => {this.input1 = c;console.log('@', c);}} type="text" placeholder="点击按钮提示数据"/>*/}
<input ref={this.saveInput} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点击显示数据</button><br/>
</div>
)
}
// 点击提示数据
showData = () => {
let {input1} = this
alert(input1.value)
}
// 回调input ref
saveInput = c => {
this.Input1 = c
}
changeWeather = () => {
let {isHot} = this.state
this.setState({isHot: !isHot})
}
}
// 2.渲染虚拟DOM到页面
ReactDOM.render(<Person/>, document.getElementById('test1'))
</script>
</body>
</html>
3 API形式refs
AP I格式上目前React官方推荐的方式,通用格式:
Class xxx extends React.Component{
xxx = React.createRef()
return {
<标签 ref={this.xxx} />
}
}
还是以最开始实例为例,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>0801_字符串形式refs</title>
</head>
<body>
<div id="test1"></div>
<!-- react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Person extends React.Component {
/*
React.createRef()调用后返回容器,存放被ref标识的结点;该容器只能存放一个结点,后放入覆盖之前。
*/
myRef1 = React.createRef()
myRef2 = React.createRef()
render() {
return (
<div>
<input ref={this.myRef1} type="text" placeholder="点击按钮提示数据" />
{/*<button ref={this.myRef1} onClick={this.showData}>点击显示数据</button><br/>*/}
<button onClick={this.showData}>点击显示数据</button><br />
<input ref={this.myRef2} type="text" placeholder="失去焦点提示数据" onBlur={this.showData1} />
</div>
)
}
// 点击提示数据
showData = () => {
alert(this.myRef1.current.value)
}
// 失去焦点提示数据
showData1 = () => {
alert(this.myRef2.current.value)
}
}
// 2.渲染虚拟DOM到页面
ReactDOM.render(<Person />, document.getElementById('test1'))
</script>
</body>
</html>
说明:
- APi创建的ref一一对应,即一个结点对应一个ref;如果多个元素使用相同的ref,最后一个覆盖前面的。
4 几种ref形式对比
- 字符串形式ref,定义使用形式简单,方便;但是官网不建议使用,虽然使用大多数情况下并不会有什么影响。
- 回调形式ref,定义和使用相对麻烦。
- API方式ref,每个元素都需要新创建一个ref,官网建议方式。
后记
❓QQ:806797785
⭐️源代码仓库地址:https://gitee.com/gaogzhen/react-study
参考:
[1]尚硅谷React教程(2022加更,B站超火react教程)[CP/OL].2020-12-15.p27-p31.

1249

被折叠的 条评论
为什么被折叠?



