引用(Refs)
何时使用 Refs
下面是几个适合使用 refs 的情况:
- 处理焦点、文本选择或媒体控制。
- 触发强制动画。
- 集成第三方 DOM 库
- 如果可以通过声明式实现,则尽量避免使用 refs。
例如,不要在 Dialog 组件上直接暴露 open() 和 close() 方法,最好传递 isOpen 属性。
为 DOM 元素添加 Ref
Nerv 支持给任意组件添加特殊属性。ref 属性接受一个回调函数,它在组件被加载或卸载时会立即执行。
当给 HTML 元素添加 ref 属性时,ref 回调接收了底层的 DOM 元素作为参数。例如,下面的代码使用 ref 回调来存储 DOM 节点的引用。
class CustomTextInput extends Nerv.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// 直接使用原生 API 使 text 输入框获得焦点
this.textInput.focus();
}
render() {
// 使用 `ref` 的回调将 text 输入框的 DOM 节点存储到 Nerv
// 实例上(比如 this.textInput)
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
Nerv 组件在加载时将 DOM 元素传入 ref 的回调函数,在卸载时则会传入 null
。ref 回调会在componentDidMount
或 componentDidUpdate
这些生命周期回调之前执行。
为了在类上设置一个属性使用 ref 回调是访问 DOM 元素的常见模式。首先的方法就如上面的例子中一样设置 ref。甚至还有更简短的写法: ref={input => this.textInput = input}
。
为类组件添加 Ref
当 ref 属性用于使用 class 声明的自定义组件时,ref 的回调接收的是已经加载的 Nerv 实例。例如,如果我们想修改 CustomTextInput
组件,实现它在加载后立即点击的效果:
class AutoFocusTextInput extends Nerv.Component {
componentDidMount() {
this.textInput.focusTextInput();
}
render() {
return (
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
);
}
}
String 类型的 Refs
除了函数类型的 Ref 之外,你还可以通过传入一个字符串,然后通过 this.refs.input
这样的形式访问到你的 Ref。但这个方式不管是 React 还是 Nerv 都是不推荐使用的(新版本的 React 将会被移除)。
class AutoFocusTextInput extends Nerv.Component {
componentDidMount() {
this.refs.textInput.focus(); // 可以通过 this.refs[yourRef] 访问
}
render() {
return (
<input
ref='textInput' />
);
}
}