文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

React ref的使用案例

2023-06-14 10:57

关注

本篇内容主要讲解“React ref的使用案例”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React 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 是啥

React 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} />    )  }}

React ref的使用案例

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

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} /> // 但是放在函数组件上无效}

React ref的使用案例

那函数组件就不能使用 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} />}

React ref的使用案例

这里贴一下官网的 tip:

React ref的使用案例

那既然函数组件也可以使用 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,是觉得状态提升后,子组件变化了会引起父组件的重新渲染,但是我只想拿数据而不引起渲染。
跟师傅说了一下我写需求时的想法,师傅见解如下:

到此,相信大家对“React ref的使用案例”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯