一、refs 和 DOM
1.1 操作DOM的入口 - ref
React
隔离了大部分DOM
,让我们不再需要操作那么多的DOM
,例如:事件绑定、添加类名、元素添加内容。- 在
react
里我们是无法通过document.getElementById
之类的方法获取DOM
元素的。 - 但有些场景中,我们仍需要操作
DOM
,此时React
就为我们提供了一个操作DOM
的接口(一个特殊的属性) —ref
。 - 以下是需要使用
ref
,即:操作DOM
的场景:- 焦点处理,文本选择或媒体控制
- 控制js动画
- 使用依赖DOM的第三方库
1.2 ref的使用
-
ref
属性采用回调函数,这个回调函数在组件被安装或卸载后将会被立刻执行。 -
当
ref
属性被用在了一个HTML
元素上,它的回调函数会接收最底层的DOM
元素作为它的参数。
1.3 实例 文本框获取焦点
import React, {Component} from "react";
import './style.css';
class Input extends Component {
handleEvent (event) {
const value = event.target.value;
this.props.onChange && this.props.onChange(value); // 通过this.props调用onChange函数
console.log(`value:${value}`);
console.log(`this:${this}`);
}
focusTextInput () {
this.input.focus(); // this.input 在ref的回调函数中通过this.input=input获取到了对应的dom元素
}
render () {
return (
<div className="input-container">
<input
onKeyUp={this.handleEvent.bind(this)}
ref={(input) => {this.input = input; }} // 使用了ref
/>
</div>
)
}
}
export default Input;
ref
的使用:ref={(input) => {this.input = input; }}
- 当组件被安装(使用)的的时候,
React
的ref
的回调函数就会返回对应的DOM
元素; 当组件被卸载(不被使用)的时候,React
的ref
的回调函数就会返回null
。
1.4 Exposing DOM ref to Parent Components
- 有时候,我们希望通过父组件去访问子组件的
DOM
节点。- 这个想法是不推荐实施的,因为它会破坏了组件的封装性,但是这偶尔会有助于触发焦点或测量子
DOM
节点的大小或位置。- 虽然可以向子组件添加
ref
,但这不是一个理想的解决方案,因为你只能获取组件实例而不是DOM
节点。
- 相反,推荐在子组件中使用
props
属性,并将其作为ref
属性附加到DOM
节点。- 这允许父代通过中间的组件将其
ref
回调传递给子节点的DOM
节点。
- 这允许父代通过中间的组件将其
// 子组件
function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} /> // ref 、 props
</div>
);
}
// 父组件
class Parent extends React.Component {
render() {
return (
<CustomTextInput
inputRef={el => this.inputElement = el} //
/>
);
}
}
Parent
传递它的ref callback
给CustomTextInput
的props
–inputRef
。- 与此同时,
CustomTextInput
将具有相同功能的作为特别的ref
属性传递个<input/>
。 -
结果:在
Parent
中的this.inputElement
被设置为与CustomTextInput
中的<input>
元素相对应的DOM节点。 - 使用
<input>
本身的ref
属性很重要,因为它告诉React
将引用附加到其DOM
节点。
1.5 ref的注意事项
- 1.不能在函数的组件上使用
ref
,因为他们并不会拥有实例。
function MyComponent () {
return <Input/>
}
class Parent extends React.Component {
render () {
return
<MyComponent
ref={(input) => this.input = input;}
/>
}
}
- 2.如果真想在函数组件中使用
ref
,可以引用DOM
元素或者一个类组件。
function CustomTextInput (props) {
// tInput必须在这里被声明,只有这样,ref的回调函数才可以引用它
let tInput = null;
function handleClick () {
input.focus();
}
return (
<div>
<input
type="text"
ref={(input) => { tInput = input; }}
/>
<input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
)
}