react中的DOM操作实现


Posted in Javascript onJune 30, 2021
目录
  • 前面的话
  • 使用场景
  • ref
    • 【HTML元素】
    • 【类组件】
    • 【函数式组件】
    • 【对父组件暴露DOM节点】
  • 非受控组件
    • 【默认值】
  • ReactDOM
    • 【render()】
    • 【unmountComponentAtNode()】
    • 【findDOMNode()】
  • 新ref

前面的话

某些情况下需要在典型数据流外强制修改子代。要修改的子代可以是 React 组件实例,也可以是 DOM 元素。这时就要用到refs来操作DOM

使用场景

下面是几个适合使用 refs 的情况

1、处理焦点、文本选择或媒体控制

2、触发强制动画

3、集成第三方 DOM 库

如果可以通过声明式实现,则尽量避免使用 refs

[注意]不要在 Dialog 组件上直接暴露 open() 和 close() 方法,最好传递 isOpen 属性

ref

React 支持给任意组件添加特殊属性。ref 属性接受一个回调函数,它在组件被加载或卸载时会立即执行

[注意]在组件mount之后再去获取ref。componentWillMount和第一次render时都获取不到,在componentDidMount才能获取到

【HTML元素】

当给 HTML 元素添加 ref 属性时,ref 回调接收了底层的 DOM 元素作为参数

React 组件在加载时将 DOM 元素传入 ref 的回调函数,在卸载时则会传入 null。ref 回调会在componentDidMount 或 componentDidUpdate 这些生命周期回调之前执行。

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }
  focus() {
    this.textInput.focus();
  }
  render() {
    return (
      <div>
        <input
          type="text"
          ref={(input) => { this.textInput = input; }} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focus}
        />
      </div>
    );
  }
}

更简短的写法如下

ref={input => this.textInput = input}

【类组件】

当 ref 属性用于使用 class 声明的自定义组件时,ref 的回调接收的是已经加载的 React 实例

class AutoFocusTextInput extends React.Component {
  componentDidMount() {
    this.textInput.focusTextInput();
  }

  render() {
    return (
      <CustomTextInput
        ref={(input) => { this.textInput = input; }} />
    );
  }
}

[注意]这种方法仅对 class 声明的 CustomTextInput 有效

【函数式组件】

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

【对父组件暴露DOM节点】

在子节点上暴露一个特殊的属性。子节点将会获得一个函数属性,并将其作为 ref 属性附加到 DOM 节点。这允许父代通过中间件将 ref 回调给子代的 DOM 节点

该方法适用于类组件和函数式组件

function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} />
    </div>
  );
}

class Parent extends React.Component {
  render() {
    return (
      <CustomTextInput
        inputRef={el => this.inputElement = el}
      />
    );
  }
}

在上面的例子中,Parent 将它的 ref 回调作为一个特殊的 inputRef 传递给 CustomTextInput,然后 CustomTextInput 通过 ref 属性将其传递给 <input>。最终,Parent 中的 this.inputElement 将被设置为与 CustomTextInput 中的 <input> 元素相对应的 DOM 节点

非受控组件

要编写一个非受控组件,而非为每个状态更新编写事件处理程序,可以使用 ref 从 DOM 获取表单值

[注意]可能通过e.target.value取得DOM值,而不用绑定react

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={(input) => this.input = input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

由于非受控组件将真实数据保存在 DOM 中,因此在使用非受控组件时,更容易同时集成React和非React代码

【默认值】

在 React 的生命周期中,表单元素上的 value 属性将会覆盖 DOM 中的值。使用非受控组件时,通常希望 React 可以为其指定初始值,但不再控制后续更新。要解决这个问题,可以指定一个 defaultValue 属性而不是 value

render() {
  return (
    <form onSubmit={this.handleSubmit}>
      <label>
        Name:
        <input
          defaultValue="Bob"
          type="text"
          ref={(input) => this.input = input} />
      </label>
      <input type="submit" value="Submit" />
    </form>
  );
}

同样,<input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked,<select> 和 <textarea> 支持 defaultValue

ReactDOM

react-dom这个软件包提供了针对DOM的方法,可以在应用的顶级域中调用,也可以在有需要的情况下用作跳出React模型的出口。但大部分组件都不应该需要使用这个包

render()
unmountComponentAtNode()
findDOMNode()

【render()】

ReactDOM.render(
  element,
  container,
  [callback]
)

渲染一个React元素,添加到位于提供的container里的DOM元素中,并返回这个组件的一个 引用 (或者对于无状态组件返回null)

如果这个React元素之前已经被渲染到container里去了,这段代码就会进行一次更新,并且只会改变那些反映元素最新状态所必须的DOM元素

【unmountComponentAtNode()】

ReactDOM.unmountComponentAtNode(container)
从DOM元素中移除已挂载的React组件,清除它的事件处理器和state。如果容器内没有挂载任何组件,这个函数什么都不会干。 有组件被卸载的时候返回true,没有组件可供卸载时返回 false

【findDOMNode()】

ReactDOM.findDOMNode(component)
如果这个组件已经被挂载到DOM中,函数会返回对应的浏览器中生成的DOM元素 。需要从DOM中读取值时,比如表单的值,或者计算DOM元素的尺寸,这个函数会非常有用。 大多数情况下,可以添加一个指向DOM节点的引用,从而完全避免使用findDOMNode 这个函数。当 render 返回 null 或者 false 时, findDOMNode 也返回 null

新ref

版本16.3 之前,React 有两种提供 ref 的方式:字符串和回调,因为字符串的方式有些问题,所以官方建议使用回调来使用 ref。而现在引入的 createRef API,据官方说是一种零缺点的使用 ref 的方式,回调方式也可以让让路了

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

然后使用current属性,即可获得当前元素

this.myRef.current

典型应用如下所示

constructor(props){
    super(props)
    this.Mask = React.createRef()
    this.MenuList = React.createRef()
  }
  handleClick = () => {
    ReactDOM.findDOMNode(this.MenuList.current).classList.toggle('transform-zero')
    ReactDOM.findDOMNode(this.Mask.current).classList.toggle('mask-show')
  }

 [注意]使用styledComponents样式化的元素暴露的接口是innerRef,而不是ref

<Wrap innerRef={this.itemRef}>

到此这篇关于react中的DOM操作实现的文章就介绍到这了,更多相关react DOM操作内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
自己动手开发jQuery插件教程
Aug 25 Javascript
jquery $.each()使用探讨
Sep 23 Javascript
浅谈javascript六种数据类型以及特殊注意点
Dec 20 Javascript
浅谈EasyUi ComBotree树修改 父节点选择的问题
Nov 07 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
Dec 14 Javascript
vue2中filter()的实现代码
Jul 09 Javascript
详解react关于事件绑定this的四种方式
Mar 09 Javascript
详解超简单的react服务器渲染(ssr)入坑指南
Feb 28 Javascript
JavaScript判断对象和数组的两种方法
May 31 Javascript
JS实现横向轮播图(初级版)
Jun 24 Javascript
jquery添加div实现消息聊天框
Feb 08 jQuery
浅谈nuxtjs校验登录中间件和混入(mixin)
Nov 06 Javascript
elementui的el-popover修改样式不生效的解决
react使用antd的上传组件实现文件表单一起提交功能(完整代码)
vue+element ui实现锚点定位
Jun 29 #Vue.js
vue实现锚点定位功能
适合后台管理系统开发的12个前端框架(小结)
原生JavaScript实现简单五子棋游戏
Jun 28 #Javascript
javascript拖曳互换div的位置实现示例
You might like
中国第一家无线电行
2021/03/01 无线电
如何在PHP中使用Oracle数据库(6)
2006/10/09 PHP
php生成略缩图代码
2012/07/16 PHP
解析PHP中一些可能会被忽略的问题
2013/06/21 PHP
对PHP语言认识上需要避免的10大误区
2014/06/12 PHP
php中实现可以返回多个值的函数实例
2015/03/21 PHP
PHP学习笔记(一):基本语法之标记、空白、和注释
2015/04/17 PHP
在PHP 7下安装Swoole与Yar,Yaf的方法教程
2017/06/02 PHP
php微信开发之音乐回复功能
2018/06/14 PHP
统计出现最多的字符次数的js代码
2010/12/03 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
2013/07/29 Javascript
使用json来定义函数,在里面可以定义多个函数的实现方法
2016/10/28 Javascript
js文件中直接alert()中文出来的是乱码的解决方法
2016/11/01 Javascript
对象不支持indexOf属性或方法的解决方法(必看)
2017/05/28 Javascript
利用Jasmine对Angular进行单元测试的方法详解
2017/06/12 Javascript
EasyUI中的dataGrid的行内编辑
2017/06/22 Javascript
JS点击缩略图整屏居中放大图片效果
2017/07/04 Javascript
轻量级富文本编辑器wangEditor结合vue使用方法示例
2018/10/10 Javascript
JS获取当前时间的实例代码(昨天、今天、明天)
2018/11/13 Javascript
vue 框架下自定义滚动条(easyscroll)实现方法
2019/08/29 Javascript
JavaScript鼠标悬停事件用法解析
2020/05/15 Javascript
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
Python中if __name__ == &quot;__main__&quot;详细解释
2014/10/21 Python
python实现周期方波信号频谱图
2018/07/21 Python
python开发之anaconda以及win7下安装gensim的方法
2019/07/05 Python
Python多叉树的构造及取出节点数据(treelib)的方法
2019/08/09 Python
python requests.get带header
2020/05/05 Python
python 解决Windows平台上路径有空格的问题
2020/11/10 Python
老海军美国官网:Old Navy
2016/09/05 全球购物
意大利包包和行李箱销售网站:Bagaglio.it
2021/03/02 全球购物
荷兰DOD药房中文官网:DeOnlineDrogist
2020/12/27 全球购物
食堂采购员岗位职责
2014/03/17 职场文书
寒暑假实习证明书模板
2014/11/29 职场文书
通报表扬范文
2015/01/17 职场文书
物业客服专员岗位职责
2015/04/07 职场文书
sql查询结果列拼接成逗号分隔的字符串方法
2021/05/25 SQL Server