获取真实的DOM节点
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref
属性(查看 demo07 )。
var MyComponent = React.createClass({ handleClick: function() { this.refs.myTextInput.focus(); }, render: function() { return ( <div> <input type="text" ref="myTextInput" /> <input type="button" value="Focus the text input" onClick={this.handleClick} /> </div> ); } }); ReactDOM.render( <MyComponent />, document.getElementById('example') );
上面代码中,组件 MyComponent
的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref
属性,然后 this.refs.[refName]
就会返回这个真实的 DOM 节点。
需要注意的是,由于 this.refs.[refName]
属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click
事件的回调函数,确保了只有等到真实 DOM 发生 Click
事件之后,才会读取 this.refs.[refName]
属性。
React 组件支持很多事件,除了 Click
事件以外,还有 KeyDown
、Copy
、Scroll
等,完整的事件清单请查看官方文档。
以上是以前的API
最新的API反对这种用法
提倡在ref属性中使用回调函数,而不是一个字符串
而在拿真实节点时不再用this.refs.[refName],而是用this.[refName]
The ref Callback Attribute #
React supports a special attribute that you can attach to any component. The ref
attribute takes a callback function, and the callback will be executed immediately after the component is mounted or unmounted.
When the ref
attribute is used on an HTML element, the ref
callback receives the underlying DOM element as its argument. For example, this code uses the ref
callback to store a reference to a DOM node:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in this.textInput.
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
React will call the ref
callback with the DOM element when the component mounts, and call it with null
when it unmounts.
Using the ref
callback just to set a property on the class is a common pattern for accessing DOM elements. The preferred way is to set the property in the ref
callback like in the above example. There is even a shorter way to write it: ref={input => this.textInput = input}
.
If you worked with React before, you might be familiar with an older API where the ref
attribute is a string, like "textInput"
, and the DOM node is accessed asthis.refs.textInput
. We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. If you're currently using this.refs.textInput
to access refs, we recommend the callback pattern instead.