如何实现 React 中的虚拟 DOM (上)
jangwoo 小马学编程 2月16日
React是Facebook开发的一款JS库,注意他不是框架而是库。Facebook 推出 React 主要是为了解决什么问题。
由于当项目变得无比庞大,结构相当复杂时,MVC很快变得非常复复杂,每次添加一项新的功能或特性时,系统的复杂度就成级数增长,致使代码变得脆弱和不可预测,这时 MVC 显得力不从心,无法应付。认为MVC不适合大规模应用,当系统中有很多的模型和相应的视图时,其复杂度就会迅速扩大,非常难以理解和调试,特别是模型和视图间可能存在的双向数据流动。
为了解决这个问题推出“以某种方式组织代码,使其更加可预测” flux 和 react(以组件为基础)。
DOM 和 virtual DOM
DOM, (Document Objecet Model), 文档对象模型,DOM定义了访问HTML或是XML文档的标准,是一种使程序动态的访问,更新HTML文档或XML文档等的内容,结构以及样式的平台,操作接口,DOM定义了文档的对象和属性,以及访问它们的接口。
Virtual DOM
VirtualDOM,虚拟DOM对象,是 React中的DOM对象。React使用JSX编写虚拟DOM对象,经过Babel编译之后会生成真正的DOM. 然后会将真正的DOM插入(Render)到页面。
由于更新 dom 成本昂贵,所以我们通过读取 virtual dom 这个低成本的对象,
然后将vitural dom 通过 js 渲染到界面
如果操作 dom 或更新了 dom ,我们可以通过 diff 方法,来对比新旧 virtual dom 后,找出不同地方,然后只更新发生变化的部分。这样来更新 dom 就大大地节省了成本,并且提供良好的用户体验。
目标:通过代码讲解 react 是如何实现 virtual dom
基本要求:熟悉 javascript 的前端开发人员涵盖内容 JSX 编译;基于 virtual dom 生成真实 dom 节点; diff 和 patch 方法是如何实现的。
由于篇幅有限我们将不会讲解 Event(事件) 组件周期 数据属性 性能和缓存
首先我们将 jsx 编译成 vdom ,然后根据 vdom 生成真实 dom。
我们先创建一个项目,然后初始化项目(npm init -y) 的 package.json 文件。
在项目目录下,创建 index.html 文件 如下图
引入使用 babel 将 index.js 编译后的 compiled.js (主要讲 jsx 文件编程)
main 标签为渲染 virtual dom 的容器。
我们安装所需的库 babel-cli 以及 babel 插件
在 .babelrc 配置文件中配置插件以及参数,有关 pragma 使用方法大家可以在 babel 官网 docs 中找到答案,如果不实用该参数默认值为 React.createElement
我们目录下创建 index.js(这个文件会被编译为 compiled.js)
我们先将要实现的方法一个一个罗列出来,然后再一个一个地去实现他。
view 方法返回一个 virtual dom 对象
如果您熟悉 react 图中的代码应该感觉很亲切吧,对这就是 jsx 格式。将 jsx 中xml 转换 javascript 方法来创建 dom
使用下面命令将 index.js 编译成 compiled.js
我们来修改 h 方法,具体可以看一下注释吧
然后我们 chrome 浏览器的控制台中输入 view() 就可以看到此方法返回一个 VMOD 对象
我们根据view生成 virtual dom 对象创建真实 dom 然后将其渲染到网页。
我们需要对node节点的所有child 应用 createElement 进行递归 node
这里我们用到 es6 新特性,如果对 es6 新特性感兴趣请观看我的优酷视频
实现为 dom 元素设置属性
到现在为止我们完成第一步将 virtual dom 渲染到界面上