React 中三种获取 DOM 引用的方式对比
在 React 中,如果需要直接操作 DOM(如聚焦输入框、读取原生表单值、集成第三方库),可以通过 ref 建立对真实节点的引用。下面依次介绍三种常见写法,并给出各自的注意点。
1. 字符串 ref(已废弃)
早期版本允许在 JSX 上写 ref="xxx",随后通过 this.refs.xxx 读取节点。写法简单,但存在性能隐患,且未来可能被移除,不推荐。
// 仅作演示,请勿在新代码中使用
class OldDemo extends React.Component {
handleClick = () => {
alert(this.refs.txt.value);
};
render() {
return (
<div>
<input ref="txt" placeholder="输入内容" />
<button onClick={this.handleClick}>获取值</button>
</div>
);
}
}
2. 回调 ref
把 ref 设为一个函数,React 会在节点挂载或卸载时调用该函数,参数即为对应 DOM 元素。
- 首次渲染:传入真实 DOM。
- 更新阶段:先传入
null卸载旧节点,再传入新 DOM。
若回调写成内联箭头函数,会导致每次渲染都重新创建函数;对性能极端敏感的场景,可改为类实例方法。
class CallbackRef extends React.Component {
// 类实例方法写法,避免重复创建函数
bindInput = el => (this.inputEl = el);
show = () => {
alert(this.inputEl.value);
};
render() {
return (
<div>
<input ref={this.bindInput} placeholder="输入内容" />
<button onClick={this.show}>获取值</button>
</div>
);
}
}
3. React.createRef
React 16.3 引入的推荐方案:先通过 createRef() 生成一个专用"容器",再把该容器赋给 ref。节点挂载后,可通过 container.current 访问。
class CreateRef extends React.Component {
// 每个 ref 对应一个独立的容器
inputRef = React.createRef();
handleClick = () => {
alert(this.inputRef.current.value);
};
render() {
return (
<div>
<input ref={this.inputRef} placeholder="输入内容" />
<button onClick={this.handleClick}>获取值</button>
</div>
);
}
}
小结
- 字符串 ref:已废弃,不再使用。
- 回调 ref:灵活,适合一次性或动态逻辑;注意内联写法带来的重复调用。
createRef:官方推荐,语法直观,容器"专人专用",避免回调地狱。
无论哪种方式,都应克制使用:React 的数据流(props / state)才是主体,ref 仅用于必须触碰 DOM 的边界场景。