React三大核心属性之二——ref
我们来通过一个案例来学习 ref 属性
1. 字符串形式的 ref (过时 API,影响效率,未来即将被淘汰)
需求: 自定义组件,功能说明如下:
1. 点击按钮,提示第一个输入框中的值
2. 当第2个输入框失去焦点时,提示这个输入框中的值
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<script type='text/babel'>
// 创建组件
class Demo extends React.Component {
showData = () => {
const input = this.refs.input1;
alert(input.value)
}
showData2 = () => {
const input2 = this.refs.input2;
alert(input2.value)
}
render() {
return (
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧数据</button>
<input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>
效果如下:
2. 回调函数形式的 ref
class Demo extends React.Component {
showData = () => {
alert(this.input1.value)
}
showData2 = () => {
alert(this.input2.value)
}
render() {
return (
<div>
<input ref={c => this.input1 = c} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧数据</button>
<input ref={c => this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
3. 回调 ref 中回调执行次数的问题
如果ref 是内联函数,那么在更新数据的时候,会执行两次,一次是释放内联函数,一次是再次创建内联函数,但是影响不大,可以使用内联,也可以使用 class 的绑定函数
1) 内联函数
class Demo extends React.Component {
state = {isHot: true};
showData = () => {
alert(this.input1.value)
}
changeWeather = () => {
const {isHot} = this.state;
this.setState({isHot: !isHot})
}
render() {
const {isHot} = this.state
return (
<div>
<h2>今天天气很{isHot ? "炎热" : "凉爽"}</h2>
<input ref={c => {this.input1 = c; console.log("@",c);}} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示输入数据</button>
<button onClick={this.changeWeather}>点我改变天气</button>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
2)class 的绑定函数
class Demo extends React.Component {
state = {isHot: true};
showData = () => {
alert(this.input1.value)
}
changeWeather = () => {
const {isHot} = this.state;
this.setState({isHot: !isHot})
}
saveInput = (c) => {
this.input1 = c
}
render() {
const {isHot} = this.state
return (
<div>
<h2>今天天气很{isHot ? "炎热" : "凉爽"}</h2>
{/*<input ref={c => {this.input1 = c; console.log("@",c);}} type="text" placeholder="点击按钮提示数据"/> */}
<input ref={this.saveInput} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示输入数据</button>
<button onClick={this.changeWeather}>点我改变天气</button>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
4. createRef
// 创建组件 class Demo extends React.Component { // React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是"专人专用" myRef = React.createRef() myRef2 = React.createRef() showData = () => { alert(this.myRef.current.value) } showData2 = () => { alert(this.myRef2.current.value) } render() { return ( <div> <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/> <button onClick={this.showData}>点我提示左侧数据</button> <input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/> </div> ) } } ReactDOM.render(<Demo/>, document.getElementById('test'))
总结ref
1. 理解
组件内的标签可以定义 ref 属性来标识自己(相当于 id )
2. 编码
1)字符串形式的 ref:最简单,但是被官网抛弃,影响效率
<input ref="input1"/>
2)回调函数形式的 ref:常用内联函数形式
<input ref={c => this.input1 = c} />
3)createRef :最麻烦,官网最推荐,目前最新用法
myRef = React.createRef()
<input ref={this.myRef} />
生活是痛苦的白天,死亡是凉爽的夜晚。