导入
引用 DOM 元素
在本节课中,我们将学习如何在 React 中操作 DOM 节点。
为什么需要与 DOM 交互?
有时你需要在 React 中与 DOM 节点进行交互。ref 属性让你能够访问元素中的节点。这通常被认为是 React 中的反模式,因为你应该使用其声明式编程方式和单向数据流。我们在介绍第一个搜索输入框时已经学过这一点,但确实存在一些必须访问 DOM 节点的场景。
官方文档提到了三种常见情况:
- 使用 DOM API 来管理焦点、媒体播放等
- 手动触发 DOM 节点的动画
- 与需要直接操作 DOM 节点的第三方库集成(例如 D3.js)
在 Search 组件中引用 DOM
我们以 Search 组件为例。当应用首次渲染时,输入框应该自动获得焦点。这就是一个需要访问 DOM API 的典型场景。ref 属性既可用于函数式无状态组件,也可用于 ES6 类组件。由于本例需要生命周期方法,因此我们通过 ES6 类组件展示 ref 的用法。
第一步是将原来的函数式无状态组件改为 ES6 类组件。
1class Search extends Component { 2 render() { 3 const { 4 value, 5 onChange, 6 onSubmit, 7 children 8 } = this.props; 9 10 return ( 11 <form onSubmit={onSubmit}> 12 <input 13 type="text" 14 value={value} 15 onChange={onChange} 16 /> 17 <button type="submit"> 18 {children} 19 </button> 20 </form> 21 ); 22 } 23}
ES6 类组件中的 this 对象可以帮助我们通过 ref 属性引用 DOM 元素。
1class Search extends Component { 2 render() { 3 const { 4 value, 5 onChange, 6 onSubmit, 7 children 8 } = this.props; 9 10 return ( 11 <form onSubmit={onSubmit}> 12 <input 13 type="text" 14 value={value} 15 onChange={onChange} 16 ref={el => this.input = el} 17 /> 18 <button type="submit"> 19 {children} 20 </button> 21 </form> 22 ); 23 } 24}
现在,可以通过 this 对象、合适的生命周期方法以及 DOM API,在组件挂载后聚焦输入框。
1class Search extends Component { 2 componentDidMount() { 3 if (this.input) { 4 this.input.focus(); 5 } 6 } 7 8 render() { 9 const { 10 value, 11 onChange, 12 onSubmit, 13 children 14 } = this.props; 15 16 return ( 17 <form onSubmit={onSubmit}> 18 <input 19 type="text" 20 value={value} 21 onChange={onChange} 22 ref={el => this.input = el} 23 /> 24 <button type="submit"> 25 {children} 26 </button> 27 </form> 28 ); 29 } 30}
当应用渲染时,输入框将自动获得焦点。在函数式无状态组件中,我们无法使用 this 对象,但仍然可以通过以下方式访问 ref:
1const Search = ({ 2 value, 3 onChange, 4 onSubmit, 5 children 6}) => { 7 let input; 8 return ( 9 <form onSubmit={onSubmit}> 10 <input 11 type="text" 12 value={value} 13 onChange={onChange} 14 ref={el => input = el} 15 /> 16 <button type="submit"> 17 {children} 18 </button> 19 </form> 20 ); 21}
现在我们可以访问输入框的 DOM 元素。不过在当前场景下,由于函数式无状态组件没有生命周期方法来触发聚焦,这个 input 变量并没有实际作用。未来你可能会遇到需要在函数式组件中使用 ref 的情况。
进一步阅读
- 阅读关于 React 中 ref 属性的使用
- 阅读关于 React 中 ref 属性的一般用法