React.js |Refs转发
Refs获取DOM对象
-
ref以字符串形式出现,通过this.refs获取
class Counter extends React.Component{ state={count:0} add=()=>{this.refs.info.textContent=++this.state.count} //获取dom对象 render(){ return( <div> <button onClick={this.add}>加1</button> <p ref="info">{this.state.count}</p> </div> ) } }
-
创建ref对象,通过refObject.current获取
class Counter extends React.Component{ state={count:0} dom=React.createRef() //1.创建ref add=()=>{this.dom.current.textContent=++this.state.count} //2.获取dom对象 render(){ return( <div> <button onClick={this.add}>加1</button> <p ref={this.dom}>{this.state.count}</p> </div> ) } }
Refs转发到DOM组件
过程简述:创建ref对象,子组件接收ref
const counterRef=React.createRef() //1.创建ref
class App extends Component {
render() {
//2. 接收ref并创建组件
const Counter=React.forwardRef((props,ref)=>(
<input ref={ref} value={props.children} type="button"/>
))
return <Counter ref={counterRef}>hello</Counter>
}
componentDidMount(){
console.log(counterRef.current)
}
}
总结Refs转发到DOM组件过程:
- 通过
React.createRef()
创建ref
- 通过
React.forwardRef()
接收ref并创建组件 - 内部组件接收
ref
在高阶组件中获取实例
下面是一个简单的高阶组件:
WrapComponent.js
function wrapComponent(OriginalComponent) {
class Extra extends React.Component {
componentDidMount() {
console.log('我是新来的')
}
render() {
return <OriginalComponent {...this.props}/>;
}
}
return Extra
}
SayHi.js
//1.导入高阶组件
import wrapComponent from './WrapComponent'
//2.原始组件
class SayHi extends React.Component{
render(){
return <h1>hello!{this.props.name}</h1>
}
}
//3.导出包装后的组件
export default wrapComponent(SayHi)
App.js
//导入包装后的组件
import SayHi from './SayHi'
class App extends Component {
render(){
return(
<SayHi name={'Lisa'}/>
)
}
}
现在获取实例:
function wrapComponent(OriginalComponent) {
class Extra extends React.Component {
componentDidMount() {
console.log('我是新来的')
console.log(this.refs.child)
}
render() {
return <OriginalComponent ref="child"/>;
}
}
return Extra
}
Refs转发到高阶组件内部
但是不想在高阶组件中写呢?
const ref=React.createRef() //1.创建ref
class App extends Component {
render(){
return(
<SayHi name={'Lisa'} ref={ref}/>
)
}
//想获取被包裹的组件
componentDidMount(){
console.log(ref.current)
}
}
//WrapComponent.js
function wrapComponent(OriginalComponent) {
class Extra extends React.Component {
componentDidMount(){
console.log('我是新来的')
}
render() {
return <OriginalComponent {...this.props}/>;
}
}
return Extra
}
可见并没有获取到被包裹的组件。这是因为ref 会引用最外层的容器组件(Extra),而不是内部组件。如何解决呢?通过React.forwardRef
将接收到的refs 以prop的方式传递到内部组件。现在改装一下高阶组件:
function wrapComponent(OriginalComponent) {
class Extra extends React.Component {
render() {
//3.接收到外层组件的prop,解构一下
const {forwardedRef, ...rest} = this.props;
//4.只需把传过来的ref(forwardedRef)定义为 ref
// 这时ref就可以挂载到被Extra包裹的子组件上了
return <OriginalComponent ref={forwardedRef} {...rest} />;
}
}
//1.在外层通过React.forwardRef接收传过来的ref
//2.在这里,ref被作为常规 prop 属性传递给 Extra。现在将传过来的ref暂时储存在forwardedRef中
return React.forwardRef((props, ref) => {
return <Extra {...props} forwardedRef={ref} />;
});
}
只在使用
React.forwardRef
定义组件的时候,参数 ref才会存在。常规函数和 class 组件不接收 ref 参数,且 props 中也不存在 ref
参考: