什么是虚拟Dom?
长话短说:虚拟Dom(Virtual DOM)只是react中用来表示dom结构的纯js对象,它用来描述元素的样子;虚拟Dom是跨平台的,和平台无关。
怎么构建虚拟Dom?
关键函数 React.createElement,html中实现的简单过程如下:
import React from 'react';
React.createElement(
'div',
{ id: 'A1', key: 'A1' },
React.createElement('div', { id: 'B1', key: 'B1' }, 'B1'),
React.createElement('div', { id: 'B2', key: 'B2' }, 'B2')
);
浏览器中得到什么?
由此我们可以看出,react内部确实可以将dom元素转化成js对象,实际上,上述代码还等价于:
let virtuaDom = (
<div id='A1' key='A1'>
<div id='B1' key='B1'> </div>
<div id='B2' key='B2'> </div>
</div>
);
React.createElement内部如何实现的?
我们来简单的看一看react内部如何实现这个功能的:
import { REACT_ELEMENT_TYPE } from ''; // react内部类型标记
/**
* 这边我们简单定义一个create函数
* RESERVED_PROPS : 保留的属性
* @param {*} type 元素类型
* @param {*} config 配置对象
* @param {*} children 子元素,可能是一个数字,可能是一个字符串 或者 元素 或者null,有可能有,有可能有一个,有可能有多个
*/
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true,
};
export function createElement(type, config, children) {
const props = {};
let key = null; // 标识每一个稳定的元素
if (config !== null) {
key = config.key;
}
for (let propName in config) {
if (!RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = propName;
}
}
const childrenLength = arguments.length - 2; // 参数从第三个开始算起
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
const childrenArr = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childrenArr[i] = arguments[i + 2];
}
props.children = childrenArr;
}
const element = {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
props,
};
return element;
}
虚拟Dom的优缺点有哪些?
1、优点
- 处理了浏览器的兼容,避免用户直接操作真实DOM
- 内容经过了XSS处理,可以防范XSS攻击
- 更容易实现跨平台
- 差异化更新,减少Dom更新次数
2、缺点
- 虚拟Dom挂载在内存中,消耗了额外内存
- 有时候不一定快(首次渲染)