React组件渲染后对DOM的操作方式

 更新时间:2023年02月13日 17:05:59   作者:成续源  
这篇文章主要介绍了React组件渲染后对DOM的操作方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

React组件渲染后对DOM的操作

在React.js中基本不需要对DOM进行操作,可以直接通过 setState 的方式重新渲染组件,渲染的时候可以把新的 props 传递给子组件,从而达到页面数据更新的效果。

但是有的时候需要组件渲染完后对DOM进行一些操作,比如表单提交后对其中的<input>中的内容进行清空,重新定义鼠标焦点,下面以1个简单的例子进行说明。

先看下显示效果

在这里插入图片描述

在上例中,组件渲染结束后,清空了文本输入框中的内容,并重新把鼠标焦点focus在文本框中,React.js 提供了 ref 属性来帮助我们获取已经挂载的元素的 DOM 节点,你可以给某个 JSX 元素加上 ref属性(本例中给<input>加上了ref属性),这个ref属性值是一个回调函数。

当 input 元素在页面上挂载完成以后,React.js 就会调用这个函数,并且把这个挂载以后的 DOM 节点传给这个函数。在函数中我们把这个 DOM 元素设置为组件实例的一个属性,这样以后我们就可以通过 this.input 获取到这个 DOM 元素。

然后我们可以在setNewColor()函数中调用this.input.value和this.input.focus,实现清空文本框输入内容,重新focus鼠标焦点的操作。

关键代码如下:给<input>增加ref属性,这样通过this.input获取input这个DOM元素,并调用相应的API。

<input
  ref={(input) => this.input = input}
  placeholder={"Please enter a color"}
  onChange={e => this.colorValue(e)}
/>

完整代码如下

class Color extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            color: '',
            bgColor: ''
        };
    }

    //获取文本框中用户输入的内容
    colorValue(e) {
        this.setState({
                color: e.target.value
            }
        );
    }

    //点击按钮后事件
    setNewColor(e) {
        this.setState({
            bgColor: this.state.color
        });

        //设置完背景颜色后,清空输入框内容,重新获得焦点
        this.input.value = "";
        this.input.focus();

        //阻止默认行为
        e.preventDefault();
    }

    render() {
        const squareStyle = {
            //如果是this.state.color,直接显示颜色,不需要点击show按钮
            backgroundColor: this.state.bgColor,
        };


        return (
            <div className={"colorArea"}>
                <div className={"colorSquare"} style={squareStyle}></div>
                <form onSubmit={e => this.setNewColor(e)}>
                    <input
                        ref={(input) => this.input = input}
                        placeholder={"Please enter a color"}
                        onChange={e => this.colorValue(e)}/>
                    <button type={"submit"}>show</button>
                </form>
            </div>
        );
    }
}


if (document.getElementById('container')) {
    ReactDOM.render(
        <div>
            <Color/>
        </div>,
        document.getElementById('container')
    );
}

React组件渲染原理

jsx如何生成element

JSX代码经过babel编译成React.createElement的表达式。element在React里,是组成虚拟DOM 树的节点,用来描述在浏览器上看到什么。它的参数有三个:

1、type -> 标签

2、attributes -> 标签属性,没有的话,可以为null

3、children -> 标签的子节点

e.g.return(
	React.createElement(
            	‘div',
            	{ className: ‘first' },
            	'Hello, world'
       	 ),
)

React.createElement的表达式会在render函数被调用的时候执行。当render函数被调用的时候,会返回一个element,element不一定是Object类型。

element如何转化成真实DOM节点的

首次渲染:

若不是Oobject类型,string、number创建ReactDOMTextComponent对象,调用该对象的mount方法。在这个mount方法中,把文本放到一个span中,调用容器组件的innerHTML,进行渲染;null、false创建ReactDOMEmptyComponent对象。

element为Object类型,若是原生DOM标签,给它创建ReactDOMComponent的实例对象,通过递归调用到ReactDOMComponent的mountComponent方法来得到真实DOM。

如果第二步render出来的element 类型是自定义组件

它就会去调用ReactCompositeComponentWrapper的mountComponent方法,从而形成了一个递归。递归调用子组件的render方法进而调用map方法,直至把自定义标签分解为前两种标签。

更新渲染:

函数setState被调用后,将传入的state放进pendingState的数组里存起来,若当前流程处于批量更新,则将当前组件的instance放进dirtyComponent里,当这个更新流程中所有需要更新的组件收集完毕之后就会遍历uptateComponent对组件进行更新。当然,如果当前不处于批量更新的状态,会直接去遍历dirtyComponent进行更新。

假设Example是自定义组件,即调用的是ReactCompositeComponentWrapper的updateComponent方法。

在这里插入图片描述

1、计算出nextState(shouldComponentUpdate)

2、render()得到nextRenderElement(componentWillUpdate可修改state)

3、与prevtElement进行Diff 比较,更新节点 (componentDidUpdate)

扩充:diff算法

两个相同的组件产生类似的DOM结构,不同组件产生不同DOM结构;

对于同一层次的一组子节点,它们可以通过唯一的id区分。

  • 不同节点类型:React将不会在去对比子节点。因为不同的组件DOM结构会不相同,所以就没有必要在去对比子节点了。
  • 相同节点类型:dom类型节点,react会对比它们的属性,只改变需要改变的属性;自定义节点类型逻辑都在React组件里面,所以它能做的就是根据新节点的props去更新原来根节点的组件实例,触发一个更新的过程,最后在对所有的child节点在进行diff的递归比较更新;
  • 子节点比较:依次比较,顺序不同即使仍存在的节点依旧会被卸载重建,可以加null保持DOM结构的稳定性,也可以给节点配置key,让React可以识别节点是否存在,只在指定位置创建节点插入。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • react中props 的使用及进行限制的方法

    react中props 的使用及进行限制的方法

    这篇文章主要介绍了react中的props 的使用及进行限制的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 如何应用 SOLID 原则在 React 中整理代码之开闭原则

    如何应用 SOLID 原则在 React 中整理代码之开闭原则

    React 不是面向对象,但这些原则背后的主要思想可能是有帮助的,在本文中,我将尝试演示如何应用这些原则来编写更好的代码,对React SOLID原则开闭原则相关知识感兴趣的朋友一起看看吧
    2022-07-07
  • React Refs 的使用forwardRef 源码示例解析

    React Refs 的使用forwardRef 源码示例解析

    这篇文章主要为大家介绍了React 之 Refs 的使用和 forwardRef 的源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • React实现Step组件的示例代码

    React实现Step组件的示例代码

    这篇文章主要为大家详细介绍了React实现Step组件(步骤条组件)的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • TypeScript在React项目中的使用实践总结

    TypeScript在React项目中的使用实践总结

    这篇文章主要介绍了TypeScript在React项目中的使用总结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 聊一聊我对 React Context 的理解以及应用

    聊一聊我对 React Context 的理解以及应用

    这篇文章主要介绍了聊一聊我对 React Context 的理解以及应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • React 小技巧教你如何摆脱hooks依赖烦恼

    React 小技巧教你如何摆脱hooks依赖烦恼

    Hooks 是一种函数,该函数允许您从函数式组件 “勾住(hook into)” React 状态和生命周期功能。 Hooks 在类内部不起作用 - 它们允许你无需类就使用 React,本文带领大家学习React 小技巧教你如何摆脱hooks依赖烦恼,感兴趣的朋友一起看看吧
    2021-05-05
  • 使用react render props实现倒计时的示例代码

    使用react render props实现倒计时的示例代码

    这篇文章主要介绍了使用react render props实现倒计时的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • 浅谈react-router@4.0 使用方法和源码分析

    浅谈react-router@4.0 使用方法和源码分析

    这篇文章主要介绍了浅谈react-router@4.0 使用方法和源码分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • React Native实现Toast轻提示和loading效果

    React Native实现Toast轻提示和loading效果

    这篇文章主要介绍了React Native实现Toast轻提示和loading效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09

最新评论