持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
refs与事件处理
理解
组件内的标签可以定义ref属性来标识自己
使用方式
1. 字符串形式的ref(已过时)
string类型的refs是最基础的一种方式,不过官网已经不推荐使用该方式来实现,因为string类型的refs存在一些问题,它可能会在未来的版本中被移除。
基础实现方式:
<!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="test"></div>
<!-- 加载 React 核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 加载 React DOM 用于支持 React 操作 DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 加载 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 设置类型为babel -->
<script type="text/babel">
// 创建组件
class RefDemo extends React.Component{
render(){
return (
<div>
<input ref='input1' type='text' placeholder='点击按钮弹窗'/>
<button onClick={this.showData1}>按钮</button>
<input onBlur={this.showData2} ref='input2' type='text' placeholder='失去焦点弹窗'/>
</div>
)
}
// 左侧数据展示
showData1 = () => {
const {input1} = this.refs
alert(input1.value)
}
// 右侧数据展示
showData2 = () => {
const {input2} = this.refs
alert(input2.value)
}
}
// 将组件渲染到页面
ReactDOM.render(<RefDemo/>, document.getElementById('test'))
</script>
</body>
</html>
2. 回调形式的ref
在实例的属性中存储对 DOM 节点的引用。需要注意的是,如果ref是以回调函数形式定义的,在更新的过程中它会被执行两次,第一次传入参数为null,然后第二次才会传入参数DOM。因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。
回调形式的实现:
<!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="test"></div>
<!-- 加载 React 核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 加载 React DOM 用于支持 React 操作 DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 加载 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 设置类型为babel -->
<script type="text/babel">
// 创建组件
class RefDemo extends React.Component{
render(){
return (
<div>
<input ref={r => this.input1 = r} type='text' placeholder='点击按钮弹窗'/>
<button onClick={this.showData1}>按钮</button>
<input ref={r => this.input2 = r} onBlur={this.showData2} type='text' placeholder='失去焦点弹窗'/>
</div>
)
}
showData1 = () => {
const {input1} = this
alert(input1.value)
}
showData2 = () => {
const {input2} = this
alert(input2.value)
}
}
// 将组件渲染到页面
ReactDOM.render(<RefDemo/>, document.getElementById('test'))
</script>
</body>
</html>
切换天气时,ref会被清除的效果如下:
3. createRef创建ref容器
<!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="test"></div>
<!-- 加载 React 核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 加载 React DOM 用于支持 React 操作 DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 加载 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 设置类型为babel -->
<script type="text/babel">
// 创建组件
class RefDemo extends React.Component{
// 每个标签需定义自己的 ref 容器
myRef1 = React.createRef()
myRef2 = React.createRef()
render(){
return (
<div>
<input ref={this.myRef1} type='text' placeholder='点击按钮弹窗'/>
<button onClick={this.showData1}>按钮</button>
<input onBlur={this.showData2} ref={this.myRef2} type='text' placeholder='失去焦点弹窗'/>
</div>
)
}
// 左侧数据展示
showData1 = () => {
console.log(this.myRef1)
alert(this.myRef1.current.value)
}
// 右侧数据展示
showData2 = () => {
alert(this.myRef2.current.value)
}
}
// 将组件渲染到页面
ReactDOM.render(<RefDemo/>, document.getElementById('test'))
</script>
</body>
</html>
小结
- 字符串形式ref:能自动收集,简单快捷,但是有一些问题,未来版本可能会移除,能避免使用尽量避免;
- 回调形式ref:内联函数会有多次调用的问题,官网给出建议可以采用
class形式来避免该问题,但多次调用问题在大多数情况下是无关紧要但,两种方式均可正常使用; - createRef形式:较为麻烦,每个标签需要定义自己的一个
ref容器,但是该方式为官网最推荐使用的一种方式。