Refs是什么

React 中的 Refs 提供了一种方式,用于访问 render 方法创建的 React元素 或 Dom节点。
本质是返回 ReactDOM.render() 返回的组件实例,如果是渲染组件则返回的是组件实例,如果渲染 dom 则返回的是具体的dom节点。

使用Refs

dom元素使用ref

1、class类组件中的dom元素绑定ref
  1. export default class ClassRef extends React.Component{
  2. constructor(props) {
  3. super(props)
  4. // 创建Refs
  5. this.myRef = React.createRef();
  6. }
  7. clickButton = () =>{
  8. // 访问Refs
  9. console.log('this.ref',this.myRef)
  10. this.myRef.current.value = 'ddsds';
  11. }
  12. render(){
  13. return (
  14. <div>
  15. <button onClick={this.clickButton}>ref点击</button>
  16. // 绑定Refs,1
  17. test:<input type="text" ref={this.myRef} />
  18. // 绑定Refs,2
  19. <input type="text" ref={(element)=>{ this.myRef = element}} />
  20. </div>
  21. )
  22. }
  23. }

image.pngimage.png
由上能发现 this.myRef.current 拿到了整个 input 节点,点击时可以如上更新input的value值
image.png

第二种绑定方法,this.myRef 直接拿到了node节点

2、hook组件中的dom元素绑定ref
  1. import React,{ useRef } from 'react';
  2. function HookRef() {
  3. // 创建Refs
  4. const myRef = useRef(null)
  5. function refClick(){
  6. // 访问Refs
  7. console.log('myRef',myRef);
  8. myRef.current.focus();
  9. }
  10. return (
  11. <div>
  12. // 绑定Refs
  13. <input ref={ myRef } type="text"/>
  14. <button onClick={ refClick }>ref click</button>
  15. </div>
  16. );
  17. }

image.pngimage.png

myRef.current 拿到的值跟上面class的是一至的,调用foucs() 方法时,input获得焦点光标选中。

组件使用ref

1、class组件使用ref
  1. import React from "react";
  2. import ClassSelfR from "../ClassSelf";
  3. export default class ClassRef extends React.Component{
  4. constructor(props) {
  5. super(props)
  6. // 创建Refs
  7. this.myRef = React.createRef();
  8. }
  9. clickButton = () =>{
  10. // 访问Refs
  11. console.log('this.ref',this.myRef)
  12. this.myRef.current.setState({tag:'hah'})
  13. }
  14. render(){
  15. return (
  16. <div>
  17. <button onClick={this.clickButton}>ref点击</button>
  18. // 绑定Refs
  19. <ClassSelfR ref={this.myRef}/>
  20. </div>
  21. )
  22. }
  23. }
  24. class ClassSelfR extends React.Component {
  25. constructor (props){
  26. super(props)
  27. this.aa = 99
  28. this.state = {
  29. tag:'wq'
  30. }
  31. }
  32. a = 9
  33. render(){
  34. return <div>{this.state.tag}</div>
  35. }
  36. }

image.png
可以看到,拿到了整个子组件ClassSelfR 的实例,且可以调用 setState 改变tag值

2、函数组件不能使用ref
  1. export default class ClassRef extends React.Component{
  2. constructor(props) {
  3. super(props)
  4. this.myRef = React.createRef();
  5. }
  6. clickButton = () =>{
  7. console.log('this.ref',this.myRef)
  8. }
  9. render(){
  10. return (
  11. <div>
  12. // This will *not* work!
  13. <button onClick={this.clickButton}>ref点击</button>
  14. <HookT ref= {this.myRef} />
  15. </div>
  16. )
  17. }
  18. }
  19. function HookT() {
  20. return <input />;
  21. }

image.png
不能在函数组件上使用ref属性,因为它们没有实例。

不正当使用Refs

将子组件dom通过ref暴露给父组件

1、Refs转发
  1. export default class ClassRef extends React.Component{
  2. constructor(props) {
  3. super(props)
  4. this.myRef = React.createRef();
  5. }
  6. clickButton = () =>{
  7. console.log('this.ref',this.myRef)
  8. }
  9. render(){
  10. return (
  11. <div>
  12. <button onClick={this.clickButton}>ref点击</button>
  13. <HookRef ref= {this.myRef} > 点击</HookRef>
  14. </div>
  15. )
  16. }
  17. }
  18. const HookRef = React.forwardRef((props, ref)=>{
  19. return(
  20. <button ref={ref}>
  21. { props.children }
  22. </button>
  23. )
  24. })

image.png
ref转发允许某些组件接收 ref,并向下传递给子组件。第二个参数 ref 只在使用 React.forwardRef 定义组件时存在。常规函数和 class 组件不接收 ref 参数,且 props 中也不存在 ref。
Ref 转发不仅限于 DOM 组件,你也可以转发 refs 到 class 组件实例中。

2、回调Refs
  1. export default class ClassRef extends React.Component{
  2. constructor(props) {
  3. super(props)
  4. this.myRef = React.createRef();
  5. }
  6. clickButton = () =>{
  7. console.log('this.ref',this.myRef)
  8. this.myRef.value = 99
  9. }
  10. render(){
  11. return (
  12. <div>
  13. <button onClick={this.clickButton}>ref点击</button>
  14. // 回调函数 当成props 传递给子组件
  15. <HookT inRef={ element => this.myRef = element}></HookT>
  16. </div>
  17. )
  18. }
  19. }
  20. function HookT( props) {
  21. return (
  22. <div>
  23. <input ref={props.inRef} type="text"/>
  24. </div>
  25. );
  26. }

image.png
点击时可以直接取到子组件的dom,并且改变了它的value值

将父组件某个dom通过ref暴露给子组件
  1. export default class ClassRef extends React.Component{
  2. constructor(props) {
  3. super(props)
  4. this.myRef = React.createRef();
  5. }
  6. render(){
  7. return (
  8. <div>
  9. test:<input type="text" ref={this.myRef} />
  10. <HookT inRef= {this.myRef}></HookT>
  11. </div>
  12. )
  13. }
  14. }
  15. function HookT( props) {
  16. return (
  17. <div>
  18. <button onClick={()=>{
  19. console.log('this.ref',props.inRef);
  20. props.inRef.current.value =99}
  21. }>
  22. click
  23. </button>
  24. </div>
  25. );
  26. }

image.png

把ref当成参数传过去,子组件可以获得父组件里的dom。嗯,可以但没必要没啥用