草庐IT

React获取DOM和获取组件实例的方式

学全栈的灌汤包 2023-04-04 原文

文章目录

React获取DOM的方式

ref获取DOM元素

在React的开发模式中,通常情况下不需要、也不建议直接操作DOM原生,但是某些特殊的情况,确实需要获取到DOM进行某些操作:

管理焦点,文本选择或媒体播放;

触发强制动画;

集成第三方 DOM 库;

我们可以通过refs获取DOM;

如何创建refs来获取对应的DOM呢?目前有三种方式:

方式一:传入字符串(这种做法已经不推荐)

在React元素上绑定一个ref字符串, 使用时通过 this.refs.传入的字符串格式获取对应的元素;

import React, { PureComponent } from 'react'

export class App extends PureComponent {
  getDom() {
    // 方式一
    console.log(this.refs.hello) // <h2>Hello World</h2>
  }
  
  render() {
    return (
      <div>
        <h2 ref="hello">Hello World</h2>
        <button onClick={() => this.getDom()}>获取DOM</button>
      </div>
    )
  }
}

export default App

方式二:传入一个对象(常用的方式, 推荐)

在react中导入createRef, 通过createRef() 方式提前创建出来一个对象, 将创建出来的对象绑定到要获取的元素上;

使用时获取到创建的对象其中有一个current属性就是对应的元素;

import React, { PureComponent, createRef } from 'react'

export class App extends PureComponent {
  constructor() {
    super()

    // 提前创建一个ref对象
    this.titleRef = createRef()
  }

  getDom() {
    // 方式二
    console.log(this.titleRef.current) // <h2>Hello World</h2>
  }
  
  render() {
    return (
      <div>
        <h2 ref={this.titleRef}>Hello World</h2>
        <button onClick={() => this.getDom()}>获取DOM</button>
      </div>
    )
  }
}

export default App

方式三:传入一个函数(了解)

该函数会在DOM被挂载时进行回调,这个函数回调时会传入一个元素对象,我们可以自己保存;

使用时,直接拿到之前保存的元素对象即可;

import React, { PureComponent, createRef } from 'react'

export class App extends PureComponent {
  getDom() {
  }
  
  render() {
    return (
      <div>
        <h2 ref="hello">Hello World</h2>
        <h2 ref={this.titleRef}>Hello World</h2>
        {/* 方式三, 回调函数会返回el, el就是我们要获取的DOM了 */}
        <h2 ref={el => console.log(el)}>Hello World</h2>
        <button onClick={() => this.getDom()}>获取DOM</button>
      </div>
    )
  }
}

ref获取组件实例

ref 的值根据节点的类型而有所不同:

当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性;

当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性;

不能在函数组件上使用 ref 属性,因为他们没有实例;

这里我们演示一下ref获取一个class组件对象的实例:

import React, { PureComponent, createRef } from 'react'

// 创建一个类组件, 作为子组件测试
class Test extends PureComponent {
  test() {
    console.log("Test");
  }
  render() {
    return <h2>Test</h2>
  }
}

export class App extends PureComponent {
  constructor() {
    super()

    this.tsetRef = createRef()
  }

  getDom() {
    // 获取组件实例
    console.log(this.tsetRef.current)
    // 可以调用组件的实例方法
    this.tsetRef.current.test()
  }
  
  render() {
    return (
      <div>
        <Test ref={this.tsetRef}/>
      </div>
    )
  }
}

export default App

函数式组件是没有实例的,所以无法通过ref获取他们的实例:

但是某些时候,我们可能想要获取函数式组件中的某个DOM元素;

这个时候我们可以通过 React.forwardRef 来绑定函数组件中的某个元素, forwardRef中接收两个参数, 参数一: props, 参数二: ref,后面我们也会学习 hooks 中如何使用ref;


import { render } from '@testing-library/react';
import React, { PureComponent, createRef, forwardRef  } from 'react'
}

// 创建一个函数组件, 作为子组件测试
// 使用forwardRef将函数包裹起来
const Foo = forwardRef(function(props, ref) {
  return (
    <h2 ref={ref}>Foo</h2>
  )
})

export class App extends PureComponent {
  constructor() {
    super()

    // 提前创建一个ref对象
    this.fooRef = createRef()
  }

  getDom() {

    // 获取函数组件中元素的DOM
    console.log(this.fooRef.current)
  }
  
  render() {
    return (
      <div>
        <Foo ref={this.fooRef}/>
      </div>
    )
  }
}

export default App

有关React获取DOM和获取组件实例的方式的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  4. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  5. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  6. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  7. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  8. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  9. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  10. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

随机推荐