React虚拟DOM原理

1.什么是虚拟DOM

我们在前端面试的时候,经常会被问到什么是虚拟DOM。这个概念,感觉很熟悉,但又说不出它到底是什么。现在我们来探索一下到底什么是虚拟DOM

首先我们看下什么是DOM,对于DOM,我们应该都很熟悉了,下面是MDN对于DOM的定义

文档对象模型 (DOM) 将 web 页面与到脚本或编程语言连接起来。通常是指 JavaScript,但将 HTML、SVG 或 XML 文档建模为对象并不是 JavaScript 语言的一部分。DOM模型用一个逻辑树来表示一个文档,树的每个分支的终点都是一个节点(node),每个节点都包含着对象(objects)。DOM的方法(methods)让你可以用特定方式操作这个树,用这些方法你可以改变文档的结构、样式或者内容。节点可以关联上事件处理器,一旦某一事件被触发了,那些事件处理器就会被执行。

虚拟DOM自然就是跟DOM有很大关系的了。我们在使用原生JS开发或者使用Jquery开发,经常就会操作DOM,但是我们使用的时候发现,每次我们改变DOM的时候,页面再次渲染,会花费不短的一段时间,这样用户体验就不太好了。如果我们每次操作的不是DOM或者每次只操作更少的DOM呢,是不是会花费的时间更短呢,基于这个想法,就有了虚拟DOM

在React中,会把DOM转换成JavaScript对象,然后再把JavaScript对象转化成DOM,这样我们对于DOM的操作,实际上是在操作这个JavaScript对象

2.DOM是如何创建虚拟DOM的

我们利用在线babel工具来看下。左边是JSX,右边是JSX经过babel转换后的效果,事实上JSX是右边这种写法的语法糖,我们在React项目中写的JSX的写法都会转换成右边这种写法。
在这里插入图片描述
在React项目中,使用以下这种写法,渲染出的效果也是一样的。

import React from 'react';
import ReactDOM from 'react-dom';

let element = React.createElement("h1", {
    id: "test",
    className: "testClass"
  }, "test");

ReactDOM.render(element, document.getElementById('root'));

现在我们来分析以下上面的代码

  • React.createElement()方法传入了3个参数,第1个参数对应的是标签名称,第2个参数是属性,第三个参数是内容,然后返回某个值
  • ReactDOM.render()方法接收了两个参数,第一个参数是刚刚提到的某个值,第二个参数是获取到的root元素,对应的是index.html中的<div id="root"></div>

在上面的代码中加入console.log(element),打印出element的值,然后看到,原来某个值是这样的:
在这里插入图片描述
由此说明:React.createElement()方法创建了虚拟DOM

3.模拟实现React.createElement()

有上图可以这个对象有多个属性,目前来说对我们比较重要的是propstype属性,所以先实现对于这两个属性的操作。
React.createElement()接收3个参数,现在要把这3个参数合并到typeprops中。
React.createElement()接收3个以上参数,说明该元素里面有多个子元素(这些子元素仍然是React.createElement()),那么把第二个参数后面的所有参数转换成数组放入children

function ReactElement(type, props) {
    const element = { type, props };
    return element;
}

function createElement(type, config = {}, children) {
    let propName;
    const props = {};  // 定义props
    for(propName in config) {
        props[propName] = config[propName];  // 复制config的属性到props中
    }

    // 处理children
    const childrenLength = arguments.length - 2;
    if(childrenLength === 1) {
        props.children = children;
    } else {
        // 有多个子元素的情况
        props.children = Array.from(arguments).slice(2);
    }

    return ReactElement(type, props);
}

加入以下代码测试下效果

const element = createElement("h1", {
    id: "test",
    className: "testClass"
  }, createElement("span", null, "span1"), createElement("span", null, "span2"));

console.log(JSON.stringify(element))

打印结果为:
在这里插入图片描述
可以看到,最终,DOM转换成了JavaScript对象

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值