reference 引用
function A (){
return (<h1>组件AAA</h1>)
}
<A ref="comA" /> // 不可这样使用,但是函数组件内部是可以使用ref的
过时方式(不要使用)
以聚焦input事件为例,以前的ref使用方式,ref 值为string已经过时,随时可能被移除(不建议使用,在16版中已不再可用)
export default class RefComp extends React.Component {
render() {
return (
<div>
<input ref="text" type="text" />
<button
onClick={() => {
console.log(this);
this.refs.text.focus()
}}>点击 </button>
</div>
);
}
}
ref值的两种形式
ref 的值根据节点的类型而有所不同:
-
当
ref
属性用于 HTML 元素时,构造函数中使用React.createRef()
创建的ref
接收底层 DOM 元素作为其current
属性。 -
当
ref
属性用于自定义 class 组件时,ref
对象接收组件的挂载实例作为其current
属性。 -
你不能在函数组件上使用 ref 属性,因为他们没有实例。
1.使用React.createRef() 创建( React 16.3 版本引入)
1.1 html 组件
export default class RefComp extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef(); // 创建ref
}
render() {
return (
<div>
<input ref={this.myRef} type="type" />
<button
onClick={() => {
this.myRef.current.focus(); // 访问 ref
}}
>
点击
</button>
</div>
);
}
}
// react 会在组建挂载是给this.myRef的current属性出入Dom元素,并在组件卸载时传入null值。
// ref 会在componentDidMount 和 componentDidUpdate 生命周期钩子触发前更新
1.2 自定义组件(类组件)
class Button extends React.Component {
render() {
return <input type="发type" ref={this.props.refs} />;
}
}
export default class RefComp extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return (
<div>
<Button refs={this.myRef} /> // 注意不要使用ref 传值,会报错
<button
onClick={() => {
this.myRef.current.focus();
}}
>
点击
</button>
</div>
);
}
}
由于通过React.createRef() 创建的是一个对象,ref等于这个对象,其实是个对象的content赋值,突发奇想,如果自定义一个对象并给他添加属性content:null,是否可以作用相同,测试结果为yes.
export default class RefComp extends React.Component {
constructor(props) {
super(props);
// this.myRef = React.createRef();
this.myRef = {
content: null
};
}
render() {
return (
<div>
<input type="type" ref={this.myRef} />
<button
onClick={() => {
this.myRef.current.focus();
}}
>
点击
</button>
</div>
);
}
}
1.3 自定义组件(函数组件)
function Button() {
return <input type="type" refs={this.props.ref} />;
}
export default class RefComp extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return (
<div>
<Button type="type" refs={this.myRef} />
<button
onClick={() => {
this.myRef.current.focus();
}}
>
点击
</button>
</div>
);
}
}
但函数组建内部是可以正常使用ref的
function Button() {
const myRef = React.createRef();
return <input type="type" refs={myRef} />;
}
2.使用函数 - 回调 Refs
export default class RefComp extends React.Component {
constructor(props) {
super(props);
this.myRef = null;
}
handleRef = el => {
this.myRef = el;
};
render() {
return (
<div>
<input type="type" ref={this.handleRef} />
/**
<input type="type" ref={el=>{this.myRef = el}} />
如果这边是这么写的话,会导致componentDidMount 和 componentDidUpdate时候,都会重新计算ref
*/
<button
onClick={() => {
this.myRef.focus();
}}
>
点击
</button>
</div>
);
}
}
其他使用和React.createRef() 相同
何时使用 Refs
直接操作dom元素中的某一个方法,或者使用自定义组件中的某一个方法
下面是几个适合使用 refs 的情况:
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
避免使用 refs 来做任何可以通过声明式实现来完成的事情。
举个例子,避免在 Dialog
组件里暴露 open()
和 close()
方法,最好传递 isOpen
属性。
ref 转发
function A(props, ref) {
return <h1 ref={ref}>{props.words}</h1>;
}
const NewA = React.forwardRef(A);
export default class RefComp extends React.Component {
myRef = React.createRef();
componentDidMount() {
console.log(this.myRef.current);
}
render() {
return <NewA ref={this.myRef} words="hello" />;
}
}
通过上例,解释ref转发,是指将ref指向组件内部某个组件(元素组件或者类组件)
React.forwardRef()
参数:函数组件(不能是类组件),该函数组件的第二个参数为传入的ref对象 返回:新的组件
如果我想给一个类组件左ref转发,有什么好的方法呢?
class A extends React.Component {
render() {
return <h1 ref={this.props.ref1}>{this.props.words}</h1>;
}
}
export default class RefComp extends React.Component {
myRef = React.createRef();
componentDidMount() {
console.log(this.myRef.current);
}
render() {
return <A ref1={this.myRef} words="hello" />;
}
}
只能使用props参数传入的方式