首页前端开发JavaScriptReact ref的使用示例

React ref的使用示例

时间2024-02-01 08:38:02发布访客分类JavaScript浏览348
导读:收集整理的这篇文章主要介绍了React ref的使用示例,觉得挺不错的,现在分享给大家,也给大家做个参考。 目录什么是 ref如何使用 ref放在 dom 元素上放在类组件上放在函数组件...
收集整理的这篇文章主要介绍了React ref的使用示例,觉得挺不错的,现在分享给大家,也给大家做个参考。
目录
  • 什么是 ref
  • 如何使用 ref
    • 放在 dom 元素上
    • 放在类组件上
    • 放在函数组件上
  • 总结

    写了一段时间的 react,99%都在写 state、PRop、useState、useEffect,对 ref 特别不熟悉,前几天做一个需求,想用 ref 实现父组件捞子组件的某个状态值,结果失败了,特此整理一下 ref 相关内容。

    什么是 ref

    官网介绍:

    在典型的 React 数据流中,props 是父组件与子组件交互的唯一方式。要修改一个子组件,你需要使用新的 props 来重新渲染它。但是,在某些情况下,你需要在典型数据流之外强制修改子组件。被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素。对于这两种情况,React 都提供了解决办法,即使用 ref 来获取 dom 或组件实例。

    如何使用 ref

    放在 dom 元素上

    这是 ref 最直接的用法

    export class Demo extends React.component {
      constructor(props) {
        suPEr(props)    this.myRef = createRef()  }
      componentDidmount() {
        console.LOG(this.myRef)  }
      render() {
        return div ref={
    this.myRef}
        >
        测试/div>
      }
    }
        

    打印看一下 ref 是啥

    可以看出,ref.current 拿到了 dom 元素,所以我们可以实现 dom 元素本身的一些功能,如 input 的聚焦:

    export class Demo extends React.COMponent {
      constructor(props) {
        super(props)    this.myRef = createRef()  }
          onClick = () =>
     {
        this.myRef.current.focus()  }
      render() {
            return (      div>
            button onClick={
    this.onClick}
        >
        聚焦/button>
            input ref={
    this.myRef}
         />
              /div>
        )  }
    }
        

    官网还提供了一种 ref 回调的形式:

    export class Demo extends React.Component {
      constructor(props) {
        super(props)    this.myRef = null  }
          onClick = () =>
     {
        this.myRef.focus()  }
      render() {
            return (      div>
            button onClick={
    this.onClick}
        >
        聚焦/button>
            input ref={
        ele =>
     this.myRef = ele}
         />
         // 这里的 ele 就是该 dom 元素      /div>
        )  }
    }
        

    放在类组件上

    其实组件跟原生 dom 差不多,也是拥有自己的 ui、一些功能的某种元素,所以将 ref 放在组件上,也可以获取到该组件的示例。

    // 子组件class Child extends React.Component {
      constructor(props) {
        super(props)    this.state = {
          name: 'xx'    }
      }
      render() {
            return div>
    子元素{
    this.state.name}
        /div>
      }
    }
    export class Demo extends React.Component {
      constructor(props) {
        super(props)    this.myRef = createRef()  }
      componentDidMount() {
        console.log(this.myRef)  }
      render() {
        return (     Child ref={
    this.myRef}
         />
        )  }
    }
        

    那既然可以获取到子组件的实例,我们就可以操作子组件了,比如文章最开始说,我想在父组件里去捞子组件的某些状态值。

    class Child extends React.Component {
      constructor(props) {
        super(props)    this.state = {
          count: 0    }
      }
            onClick = () =>
     {
        this.setState({
    count: this.state.count+1}
    )  }
      render() {
        return button onClick={
    this.onClick}
        >
    点击+1:{
    this.state.count}
        /button>
      }
    }
    export class Demo extends React.Component {
      constructor(props) {
        super(props)    this.myRef = createRef()  }
          onClick = () =>
     {
        console.log(this.myRef.current.state.count) // 拿到子组件的状态值  }
      render() {
            return (      div>
            button onClick={
    this.onClick}
        >
        获取子组件的点击次数/button>
            Child ref={
    this.myRef}
         />
         // ref 获取到子组件实例      /div>
        )  }
    }
        

    既然能拿值,我也能拿函数去修改子组件

    class Child extends React.Component {
      constructor(props) {
        super(props)    this.state = {
          name: 'xx'    }
      }
          changeName = () =>
     {
        this.setState({
    name: 'ww'}
    )  }
      render() {
            return div>
    子元素{
    this.state.name}
        /div>
      }
    }
    export class Demo extends React.Component {
      constructor(props) {
        super(props)    this.myRef = createRef()  }
          onClick = () =>
     {
        this.myRef.current.changeName() // 父组件的手伸到子组件里去啦  }
      render() {
            return (      div>
            button onClick={
    this.onClick}
        >
        改变子组件的状态/button>
            Child ref={
    this.myRef}
         />
              /div>
        )  }
    }
        

    当然这个例子并不恰当,父组件想更改子组件的状态的话,应该把状态提升到父组件中,然后作为子组件的props传递进去。
    主要是 ref 提供一种方式去绕过 props 来实现父子组件通信。

    放在函数组件上

    这是我文章开头写需求时犯的错,ref 不能放在函数组件上,因为函数组件没有实例。

    const Child = () =>
     {
          return div>
        子组件/div>
    }
        export const Demo = () =>
     {
          const myRef = useRef() // 可以在函数组件内创建 ref  useEffect(() =>
     {
        console.log(myRef)  }
    , [])  return Child ref={
    myRef}
         />
     // 但是放在函数组件上无效}
        

    那函数组件就不能使用 ref 了吗,那肯定不是哈哈。我们可以使用 forwardRef 包装函数组件。

    const Child = (props, ref) =>
     {
     // 包装后,除了原有的 props 外, ref 也被传了进来  return div ref={
    ref}
        >
        子组件/div>
     // 还是得挂载到 dom 上}
        const ProChild = React.forwardRef(Child) // 重点在这里export const Demo = () =>
     {
          const myRef = useRef()  useEffect(() =>
     {
        console.log(myRef)  }
    , [])  return ProChild ref={
    myRef}
         />
    }
        

    这里贴一下官网的 tip:

    那既然函数组件也可以使用 ref 的话,我们用函数组件实现一下父组件捞子组件的数据,不过可以看出,使用 forwardRef 包裹后,ref 还是得挂载到 dom 或者类组件上,如果我只想挂载数据还需要搭配 useimperativeHandle。

    const Child = (props, ref) =>
     {
          const [count, setCount] = useState(0)  useImperativeHandle(    ref,    () =>
     ({
           // 这里就是暴露给外部 ref 的数据      getVal: ()=>
     count    }
        ),    [count],  )  const onClick = () =>
     {
            setCount(pre =>
     pre+1)  }
      return button onClick={
    onClick}
        >
    点击+1:{
    count}
        /button>
    }
        const ProChild = React.forwardRef(Child)export const Demo = () =>
     {
          const myRef = useRef()  const onClick = () =>
     {
        console.log(myRef.current.getVal()) // 拿到子组件的值  }
          return >
    button onClick={
    onClick}
        >
        获取子组件的点击次数/button>
    ProChild ref={
    myRef}
         />
        />
    }
        

    至此完成了做需求时留下的问题 ✅

    总结

    最后还是需要强调一下,父组件获取子组件状态的场景,一般还是状态提升 + 回调来通信,需求最终也是使用这种方式来实现的,最开始之所以想用 ref,是觉得状态提升后,子组件变化了会引起父组件的重新渲染,但是我只想拿数据而不引起渲染。
    跟师傅说了一下我写需求时的想法,师傅见解如下:

    • 优先考虑状态提升
    • 有性能问题的话,考虑状态提升 + memo
    • 不想给多个组件加 memo 的话,就要考虑引入 redux/mobx 了
    • 如果引入 redux/mobx 是一种成本的话,那 ref 也不是不可以哈哈哈

    以上就是React ref的使用详解的详细内容,更多关于React ref的使用的资料请关注其它相关文章!

    您可能感兴趣的文章:
    • React forwardRef的使用方法及注意点
    • vue3组合API中setup、 ref、reactive的使用大全
    • 如何深入理解React的ref 属性
    • React三大属性之Refs的使用详解
    • React中useRef的具体使用
    • React中Ref 的使用方法详解
    • 详解react-refetch的使用小例子
    • 学习React中ref的两个demo示例
    • React中的refs的使用教程
    • React组件refs的使用详解
    • React Native中的RefreshContorl下拉刷新使用
    • 详解Ref在React中的交叉用法

    声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

    Reactref

    若转载请注明出处: React ref的使用示例
    本文地址: https://pptw.com/jishu/595170.html
    asp.net中显示1至20相同数字相乘的结果,若值比50小就不显示 asp.net显示相同数字相乘的结果,直到数值大于150为止

    游客 回复需填写必要信息