应用场景:有时候我们需要拿到一个特定的元素,进行特定的操作。
当然我们可以用JS操作DOM通过id直接获取:
document.getElementById('input').setAttribute('style', 'color:blue');
但这样很麻烦啊,如果用JQuery还好说,不然的话可真是难受死了。
好在React提供了一种类似的方法:ref
基础使用:
1.创建ref
创建ref很简单,直接在React元素上声明属性即可:
基础的html组件和自定义组价都可以用哦。
这个ref就会被React发现,然后加入this.refs中。
2.使用ref
直接从this.refs中取出即可。
这里用console.log()打印出了this.refs的内容,你可以查看数据,就会发现我们已经拿到了ref实例:
注意:ref是在渲染时期创建的,所以要在挂载后使用:
componentDidMount() {
console.log(this.refs);
}
这样基础的ref创建和使用就完毕了。
接下来是高级部分:ref转发!
问题:如果我想将让父组件得到子组件的ref,由此控制具体的子元素怎么办?
由于React推荐单向数据流,所以让子组件创建一个ref,再传递给父组件,这样的方法是不推荐的,也得不到React很好的支持。
解决思路:父组件创建ref,向下传递给子组件。
正常人(我)的思路(行不通=-=):
父组件:
class Parent extends React.Component {
constructor(props) { super(props); }
render(){
return (
);
}
}
ReactDOM.render( , document.getElementById('root'));
会警告:
Warning: Child: `ref` is not a prop.
因为ref属于特殊属性,不会成为props的参数内容。
解决方法:
1.创建特殊的、专门用来传递ref的组件( 我觉得很麻烦哎,直接让我传不好嘛 ,不然设置refChile这种特殊特殊参数也好嘛):
//失去被ref权利的可怜的组件:
const Parent = React.forwardRef((props, ref) => (
));
可以看到,React.forwardRef把props和ref独立了出来,ref就作为参数存在啦.
2.创建特殊的ref:
特殊的组件配合特殊的ref创建方式:此处的ref需要用React.createRef()创建.
//创建特殊的自定义ref
const ref = React.createRef();
3.使用特殊的ref:
将ref做为值传递(奥利给!):
const inputRef = React.createRef();
class App extends React.Component {
constructor(props) { super(props); }
render() {
return ( );
//请尝试比一下这个设置:
}
componentDidMount() {
console.log(this.refs);
console.log(inputRef);
}
}
用console.log()打印的结果可以作为对比:
//console.log(this.refs);
{}
//console.log(inputRef);
{current: input}
可以看到特殊的ref也有特殊的读取方式。
补充:
React.forwardRef()组件只起传递作用,
ref='inputRef'就是传递字符串,使用这种声明方式,ref会被this.refs识别并保存,因此可以用this.refs来访问注册的子组件。
ref={inputRef}就是使用单独的ref变量来保存,因此单独通过inputRef变量来访问子组件。
可运行的代码(为自己准备的,万一下次忘了呢 ):
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const Parent = React.forwardRef((props, inputRef) => (
));
const inputRef = React.createRef();
class App extends React.Component {
constructor(props) { super(props); }
render() {
//return ( );
return ( );
}
componentDidMount() {
console.log(this.refs);
console.log(inputRef);
}
}
ReactDOM.render( , document.getElementById('root'));
Ref转发本质:
ref转发并不是什么高深难懂的东西,它的原理有点白痴:
声明一个不能使用ref 的组件,那它就只能把ref当参数传递下去了。
太可怜了,有点因噎废食的感觉,那么问题来了: