ref转发及使用,forwardRef取消指向
ref转发:组件外部访问组件内部元素
一.方式:1.ref字符串:内部组件通过this.ref获取对应元素
2.通过createRef创建ref对象的current属性获取对应元素(推荐)
二.使用:
ref指向虚拟DOM,获取真实DOM
ref指向组件,获取组件实例化对象, 二者只能指向一个
第一步 creatRef创建ref对象
第二步 将ref对象传递给组件 (不要用ref属性传递ref对象)
第三步 在组件中,将ref对象指向内部的虚拟DOM (ref对象只能指向类组件,不能指向函数组件)
三.forwardRef
取消ref对象对组件的指向(包括类组件和函数组件)
参数是回调函数
回调函数参数 属性对象 ,被取消指向的ref对象
返回值 渲染的组件
ref指向类组件:
import React, {Component, createRef} from 'react';
import {render} from 'react-dom';
// 2在外部创建ref对象
let refObj = createRef();
class App extends Component {
// 组件创建完成
// componentDidMount() {
// //1.内部通过this.refs访问
// this.refs.exp.style.color = 'red'
// }
render() {
console.log(this.props);
return (
<div>
{/* <h1 ref="exp">举例1</h1> */}
{/*2 ref对象指向虚拟DOM,但直接使用外部ref对象 内部变量与外部变量耦合*/}
{/* <h1 ref={refObj}>举例2</h1> */}
{/*4 一旦指向组件App 内部就无法指向虚拟DOM,所以换一个名字*/}
{/* <h1 ref={this.props.ref}>举例3</h1> */}
{/*5 ref指向一个,指向多个会产生覆盖问题 后面覆盖前面 */}
<h1 ref={this.props.refNew}>举例4</h1>
<h1 ref={this.props.refNew}>举例5</h1>
<h1>举例</h1>
</div>
)
}
}
// 3.为避免发生2的耦合将ref对象传递,此时ref指向组件App
// render(<App ref={refObj}></App>, document.getElementById('app'), () => {
// console.log('渲染完成',refObj);
// // 在组件外部访问内部
// // refObj.current.style.color = 'red';
// })
/*解决方法: 让新的指向组件App, 让ref指向虚拟DOM即可 */
render(<App refNew={refObj}></App>, document.getElementById('app'), () => {
console.log('渲染完成',refObj);
// 在组件外部访问内部
refObj.current.style.color = 'red';
})
ref不能指向函数组件:
import React, {Component, createRef} from 'react';
import {render} from 'react-dom';
// 在外部创建ref对象
let refObj = createRef();
// 函数组件
function App(props) {
console.log(props);
return(
<div>
<h1>举例1</h1>
<h1 ref={props.refNewT}>举例2</h1>
{/* 同样不要重复使用 */}
<h1 ref={props.refNewT}>举例3</h1>
</div>
)
}
// ref对象不能指向函数组件
// 报错Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?in App
// render(<App ref={refObj}></App>, app, () => {
// console.log('render', refObj );
// })
render(<App refNewT={refObj}></App>, app, () => {
console.log('render', refObj);
// 组件外部访问组件内部的元素
refObj.current.style.color = 'red';
})
为了使ref能够指向函数组件React提供了forwardRef 函数组件的取消
import React, {Component, createRef, forwardRef} from 'react';
import {render} from 'react-dom';
// 在外部创建ref对象
let refObj = createRef();
// 函数组件
function App(props) {
console.log(props);
return(
<div>
<h1>举例1</h1>
<h1 ref={props.refRep}>举例2</h1>
{/* 同样不要重复使用 */}
<h1 ref={props.refNewT}>举例3</h1>
</div>
)
}
let DealApp = forwardApp((props, ref) => {
// 此时取消ref对象,要取消在App上的ref就要换一个名称让ref取消
return <App {...props} refRep={ref} ></App>
})
// render(<App ref={refObj}></App>, app, () => {
// console.log('render', refObj );
// })
render(<DealApp ref={refObj} msg='zihui'></DealApp>, app, () => {
console.log('render', refObj );
refObj.current.style.color = 'red';
})
类组件的取消:
import React, {Component, createRef, forwardRef} from 'react';
import {render} from 'react-dom';
let refObj = createRef();
class App extends Component {
render() {
console.log(this.props);
return (
<div>
<h1 ref={this.props.refRep}>举例1</h1>
// 同样不能重复
<h1 ref={this.props.refRep}>举例2</h1>
<h1>举例</h1>
</div>
)
}
}
let DealApp = forwardRef((props, ref) => {
// console.log(...args);
return <App {...props} refRep={ref}></App>
})
// ref指向组件就不能指向虚拟DOM 所以取消指向组件App
// render(<App ref={refObj}></App>, document.getElementById('app'), () => {
// console.log('渲染完成',refObj);
// // 在组件外部访问内部
// // refObj.current.style.color = 'red';
// })
render(<DealApp ref={refObj} num={100}></DealApp>, app, () => {
console.log('渲染完成', refObj);
refObj.current.style.color = 'red';
})
高级组件中ref应用
import React, { Component, createRef, forwardRef } from 'react';
import { render } from 'react-dom';
console.log(React);
// 组件
class App extends Component {
constructor(props) {
super(props);
// 状态
this.state = {
msg: ''
}
// 创建ref对象
this.dom = createRef();
}
// 组件创建完成
componentDidMount() {
// console.log(this.dom);
this.dom.current.style.color = 'red';
}
render() {
let { msg } = this.state;
return (
<div>
<input type="text" value={msg} onChange={e => this.setState({ msg: e.target.value })} />
<hr />
<HighCompDemo msg={msg} ref={this.dom}></HighCompDemo>
</div>
)
}
}
class Demo extends Component {
render() {
// console.log(this.props, 222);
return (
<div>
<h1 ref={this.props.HighCompRef}>demo: {this.props.msg}</h1>
</div>
)
}
}
// 定义高阶函数不能修改原组件
function highComp(Comp) {
// 定义新的组件
class HighComp extends Component {
// 修改的是新的包装组件,原组件不受影响
// 监听属性的变化
componentWillReceiveProps(props) {
console.log(222, props);
}
render() {
// console.log(this.props, 111);
// 转发给原组件
return <Comp {...this.props}></Comp>;
}
}
// 返回新的组件
// return HighComp;
// 取消指向
return forwardRef((props, ref) => <HighComp {...props} HighCompRef={ref}></HighComp>)
}
// 拓展高阶组件
let HighCompDemo = highComp(Demo);
render(<App></App>, app)

浙公网安备 33010602011771号