React入门 Part8

虚拟DOM

虚拟DOM是和真实DOM相对应的,真实DOM也就是平常说的DOM。

真实DOM是对结构化文本的抽象表达。在Web环境中,就是对HTML文本的一种抽象描述,每一个HTML元素对应一个DOM节点,HTML元素的层级关系也会体现在DOM节点的层级上,所有的这些DOM节点构成一棵DOM树。

在传统的前端开发中,通过调用浏览器提供的一组API直接对DOM执行增删改查操作。对DOM进行增删改查操作,每一次对DOM的修改都会引起浏览器对页面的重新布局和重新渲染,这个过程是十分耗时的。

前端性能优化的一条原则:尽量减少DOM操作。

虚拟DOM建立在真实DOM之上,对真实DOM的抽象。

虚拟DOM使用普通的JS对象来描述DOM元素,实际上React元素本身就是一个虚拟DOM节点。

DOM结构示例:

<div>
    <h1>
        hello world!
    </h1>
</div>

使用如下JS对象来描述上述DOM结构:

{
    type: 'div',
    props: {
        children: {
            type: 'h1',
            props: {
                children: 'hello world!'
            }
        }
    }
}

有了虚拟DOM,在需要操作DOM时,不必操作真实DOM,而且访问JS对象的效率要比访问真实DOM的效率要高。

Diff算法

React采用声明式的API描述UI结构,每次组件的状态或者属性更新,组件的render方法都会返回一个新的虚拟DOM对象,用来表达新的UI结构。

如果每次render都直接使用新的虚拟DOM来生成真实DOM结构,那么会带来大量对真实DOM的操作,从而影响程序执行效率。

实际上,React会通过比较两次虚拟DOM结构的变化找出差异部分,更新到真实DOM上,从而减少最终要在真实DOM上执行的操作,提高执行效率,这一过程就是React的调和过程,其中的关键是比较两个树形结构的Diff算法。

在Diff算法中,比较的双方是新的虚拟DOM和旧的虚拟DOM,而不是虚拟DOM和真实DOM,只不过Diff算法的结果会被更新到真实DOM上。

React通过总结DOM的实际使用场景提出了两个在绝大多数实践场景下都成立的假设:

  • 如果两个元素的类型不同,那么它们将生成两棵不同的树;
  • 为列表中的元素设置Key属性,用Key表示对元素在多次render过程中是否发生变化;

基于这两个假设,React实现了在O(N)时间复杂度内完成两棵虚拟DOM树的比较。

React对于不同情况,进行的不同操作:

  • 当根节点是不同类型时

    根节点类型的变化是一个很大的变化,React会认为新的树和就的树完全不同,不会再继续比较其他的属性和子节点,而是把整棵树拆掉重建(包括虚拟DOM树和真实DOM树)。

    这里需要注意,虚拟DOM的节点类型分为两类:一类是DOM元素类型,一类是React组件类型。

    在旧的虚拟DOM树被拆除的过程中,旧的DOM元素类型的节点会被销毁,旧的React组件实例的componentWillUnmount会被调用;

    在重建的过程中,新的DOM元素会被插入DOM元树中,新的组件实例的componentWillMount和componentDidMount方法会被调用;

    重建后的新的虚拟DOM树又会被整体更新到真实DOM树中,该过程需要大量DOM操作,更新效率最低。

  • 当根节点是相同的DOM元素类型时

    如果两个根节点是相同类型的DOM元素,React会保留根节点,而比较根节点的属性,然后只更新那些发生变化了的属性,虚拟DOM树和真实DOM树中对应的属性都会被更新。

  • 当根节点是相同的组件类型时

    如果两个根节点是相同类型的组件,对应的组件实例不会被销毁,只是执行更新操作,同步变化的属性到虚拟DOM树上,在此过程中,组件实例的componentWillReceiveProps(已不建议使用)和componentWillUpdate会被调用。

    注意,对于组件类型的节点,React无法直接知道如何更新真实DOM树,需要在组件更新并且render方法执行完成后,根据render返回的虚拟DOM结构决定如何更新真实DOM树。

    比较完成根节点后,React会以同样的原则继续递归比较子节点,每一个子节点相对于其层级以下的节点来说又是一个根节点。如此递归比较,直到比较完两棵树上的所有节点,计算得到最终的差异,更新到真实DOM树中。

    当一个节点有多个子节点时,默认情况下,React只会按照顺序逐一比较两棵树上对应的子节点。

    但如果在子节点的开始位置新增一个节点,此情况会导致每一个子节点都会被修改,为解决这种低效的更新方式,React提供了Key属性。

    当一组子节点定义了key,React会根据key来匹配子节点,每次渲染之后,只要字节点的key值没有变化,React就会认为这是同一个节点。定义Key之后,React就能判断出哪个节点发生了变化,而只更新变化的节点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React 是一个用于构建用户界面的 JavaScript 库。它被 Facebook 开发,用于构建 Facebook 和 Instagram 等应用程序的用户界面。React 通过组件化的方式构建用户界面,使得代码更易于维护和复用。下面是一个简单的 React 入门指南: 1. 安装 React React 可以通过 NPM 安装,可以在命令行中执行以下命令来安装 React: ``` npm install react react-dom ``` 2. 创建 React 组件 在 React 中,一个组件就是一个 JavaScript 类。下面是一个简单的组件示例: ```javascript import React from 'react'; class HelloWorld extends React.Component { render() { return <div>Hello World!</div>; } } export default HelloWorld; ``` 这个组件只是简单地渲染一个 `Hello World!` 的文本。 3. 渲染组件 要在页面中渲染组件,需要使用 `ReactDOM.render()` 方法。下面是一个简单的示例: ```javascript import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './HelloWorld'; ReactDOM.render( <HelloWorld />, document.getElementById('root') ); ``` 这个示例中,我们首先导入了 `ReactDOM` 和 `HelloWorld` 组件,然后使用 `ReactDOM.render()` 方法将 `HelloWorld` 组件渲染到页面上。在这个示例中,我们将组件渲染到了一个 ID 为 `root` 的元素中。 这只是 React入门React 还有很多其他的概念和功能,比如 JSX、状态、生命周期等等。如果您想深入了解 React,可以查看 React 官方文档,里面有很多有用的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值