ref 顾名思义我们知道, 其实它就可以被看座是一个组件的参考, 也可以说是一个标识作为组件的属性, 其属性值可以是一个字符串也可以是一个函数
其实, ref 的使用不是必须的即使是在其适用的场景中也不是非用不可的, 因为使用 ref 实现的功能同样可以转化成其他的方法来实现但是, 既然 ref 有其适用的场景, 那也就是说 ref 自有其优势关于这一点和 ref 的适用场景, 官方文档中是这样说的:
在从 render 方法中返回 UI 结构之后, 你可能想冲出 React 虚拟 DOM 的限制, 在 render 返回的组件实例上调用某些方法通常来说, 这样做对于应用中的数据流动是不必要的, 因为活跃的数据 (Reactive data) 流总是确保最新的 props 被传递到每一个从 render() 输出的子级中去然而, 仍然有几个场景使用这种方式是必须的, 或者说是有益的: 查找渲染出的组件的 DOM 标记(可以认为是 DOM 的标识 ID), 在一个大型的非 React 应用中使用 React 组件或者是将你现有的代码转化成 React
下面我们来看这样的一个场景 (下面的例子经常被用于 ref 的讲解, 可见下面描述的场景应该是比较经典的): 通过某个事件使 < input /> 元素的值被设为空字符串, 然后使该 < input />元素获得焦点
- var App = React.createClass({
- getInitialState: function() {
- return {userInput: ''};
- },
- handleChange: function(e) {
- this.setState({userInput: e.target.value});
- },
- clearAndFocusInput: function() {
- this.setState({userInput: ''}); // 设置值为空字符串
- // 这里想要实现获得焦点
- },
- render: function() {
- return (
- <div>
- <input
- value={this.state.userInput}
- onChange={this.handleChange}
- />
- <input type="button"
- value="Reset And Focus"
- onClick={this.clearAndFocusInput}
- />
- </div>
- );
- }
- });
在上面例子中, 我们已经实现了点击按钮通知 input 元素将值设为空字符串, 但是还没有实现使 input 元素获得焦点这实现起来有些困难, 因为在 render()中返回的并不是实际的子组件的组合, 仅仅是一个特定时间特定实例的描述这句话感觉挺绕的, 其实 render 返回的是虚拟的 DOM, 并不是真实的 DOM 因此我们不需要仅仅着眼于那些从 render()中返回的那些组件
那说到这, 对于我们如何实现获得焦点并没有太大的帮助要想实现获得焦点这个功能我们需要借助 ref 来实现上面我们提到过 ref 的值有两种类型, 一种是字符串一种是回调函数
ref 字符串上属性
React 支持一个特殊的属性, 你可以将这个属性加在任何通过 render()返回的组件中这也就是说对 render()返回的组件进行一个标记, 可以方便的定位的这个组件实例这就是 ref 的作用
ref 的形式如下
<input ref="myInput" />
要想访问这个实例, 可以通过 this.refs 来访问:
this.refs.myInput
先前版本中, 我们可以通过 React.findDOMNode(this.refs.myInput)来访问组件的 DOM 但是现在, 已经放弃了 findDOMNode 函数了, 可以直接使用 this.refs.myInput 来进行访问
ref 回调函数
ref 属性也可以是一个回调函数而不是一个名字 这个函数将要在组件被挂载之后立即执行这个参照的组件将会作为该函数的参数, 这个函数可以立即使用这个组件参数, 当然也可以将其保存供以后使用
其形式也比较简单:
- render: function() {
- return <TextInput ref={(c) => this._input = c} } />;
- },
- componentDidMount: function() {
- this._input.focus();
- },
或者是
- render: function() {
- return ( < TextInput ref = {
- function(input) {
- if (input != null) {
- input.focus();
- }
- }
- }
- />
- );
- },/
这里需要注意, 当这个参照组件被卸载并且这个 ref 改变的时候, 先前的 ref 的参数值将为 null 这将有效的防止了内存的泄露所以在上面代码中会有 if 判断:
- if (input != null) {
- input.focus();
- }
上面介绍了 ref 的使用场景和方法, 下面我们就将上面的例子来补充完整, 从而实现获得焦点的功能
- var App = React.createClass({
- getInitialState: function() {
- return {
- userInput: ''
- };
- },
- handleChange: function(e) {
- this.setState({
- userInput: e.target.value
- });
- },
- clearAndFocusInput: function() {
- this.setState({
- userInput: ''
- }); // Clear the input
- // We wish to focus the <input /> now!
- if (this.refs.myTextInput !== null) {
- this.refs.myTextInput.focus();
- }
- },
- render: function() {
- return ( < div > <input value = {
- this.state.userInput
- }
- onChange = {
- this.handleChange
- }
- ref = myTextInput / ><input type = "button"value = "Reset And Focus"onClick = {
- this.clearAndFocusInput
- }
- />
- </div > );
- }
- });
- ReactDOM.render( < App / >, document.getElementById('content'));
在这个例子中, render 函数返回一个 <input /> 实例的描述但是真正的实例通过 this.refs. myTextInput 获取只要 render 返回的某个子组件带有 ref="myTextInput" ,this.refs. myTextInput 就会获取到正确的实例
来源: http://www.jb51.net/article/134829.htm