一种基于数据驱动模型的VirtualDOM树的构建方法

2018-04-11 06:57校丽丽
西南科技大学学报 2018年1期
关键词:视图代码页面

校丽丽 杨 雷 吴 珏

(西南科技大学计算机科学与技术学院 四川绵阳 621010)

随着Web技术的快速发展和移动互联网时代的到来[1],越来越多的数据处理和业务逻辑处理开始偏向于前端,使得前端对性能的要求越来越高,传统的Web技术已经不能满足用户需求。传统的Web技术操作对象是DOM(Document Object Model)[2-3],即文档对象模型。DOM以一种独立于平台和语言的方式访问和修改一个文档的内容和结构,是表示和处理一个HTML或XML文档的常用方法[4]。DOM树是由页面中的标签创建而成[5],其结构在一定程度上反映了页面的内容及内容之间的关系[6]。DOM操作繁琐复杂,当DOM树结构、元素的几何属性、窗口大小以及元素内容发生变化时,会引起DOM的重绘和回流,并且在操作过程中,也会出现以下几个问题:

(1) 操作复杂、易出错。DOM树操作需复杂选择器,每次操作DOM树,需清楚记得DOM节点的id或者class。

(2) 兼容性较差。在动态网页中,元素绑定和删除事件的方法不同,在IE中绑定和删除事件的方法分别是attachEvent()和detachEvent();而在FireFox中绑定和删除事件分别为addEventListener()和removeEventListener()。

(3) 渲染速度缓慢,浪费资源。对于一个数据很大的列表,若只有一条数据变化或一个DOM节点的尺寸发生变化的情况,整个DOM树需重新编译和渲染,降低其渲染速度,浪费大量资源。

(4) 扩展DOM属性和数据处理方法存在较大的局限性。

针对以上问题,本文提出一种基于数据驱动模型[7]的VirtualDOM树的构建方法,此方法操作对象不是DOM节点,而是数据,通过数据来控制渲染、指令和表达式扩展DOM功能,增强数据驱动的能力,提高DOM节点灵活性、开发效率和应用性能。

1 数据驱动模型

数据是程序的核心,代码的实现总是和数据结构紧密相关。在软件开发过程中,数据驱动是尽可能将复杂的设计从程序代码转移至数据,从而降低程序设计的复杂度。数据驱动模型以数据为中心,使视图处于从属地位。数据驱动模型要求在编程时将模板代码和数据结构划分清楚。在改变程序逻辑的时候,只需修改数据,而不需修改模板代码,实时反映数据的真实变化。相对于传统的程序逻辑解决问题,使用数据驱动模型具有以下优点:

(1) 易修改。当增加新的逻辑时,只需修改数据,不需修改模板代码。

(2) 控制复杂度。通过把程序逻辑的复杂度转移至更容易处理的数据中来,从而达到控制复杂度的目标。

(3) 隔离变化。当程序逻辑发生变化,只需修改逻辑代码,并不影响模板代码,从而实现隔离。

(4) 实现重用。在开发过程中,会出现部分逻辑相同,只是处理函数不同的情况,对相同代码进行提取,实现代码重用。

2 VirtualDOM及其创建

2.1 指令和表达式

指令的作用是操作DOM元素节点。将指令绑定在DOM元素节点上时,会给绑定的DOM元素节点添加一些特殊行为,因此可将其视作特殊的HTML属性。表达式是使用双重大括号(“{{}}”)绑定的JavaScript[8]代码块,当表达式的值改变时,将其产生的连带影响响应式地作用于DOM。

指令一般分为内置指令和自定义指令两种。内置指令是前端框架定义好的指令,可直接使用。自定义指令即用户自己定义的指令,其作用是扩展元素属性、操作DOM更加简单。常见的内置指令有以下几种:

(1) 条件判断指令。根据其后表达式bool值来判断插入或删除元素。

(2) 条件渲染指令。与条件判断指令类似,都是判断元素是否显示。不同的是,条件渲染指令无论其后表达式的值为true或false,元素都会存在于HTML代码中,而条件判断指令只有值为true时,其元素才会存在于HTML代码中。

(3) 循环指令。基于一个数组渲染一个列表,类似于JavaScript遍历。

2.2 VirtualDOM

为解决传统DOM所存在的问题,采用基于数据驱动模型的VirtualDOM树提高编译、渲染性能以及扩展更多DOM属性和数据处理方法。VirtualDOM是轻量级JavaScript对象,其执行在JavaScript引擎[9]中。VirtualDOM的生成给DOM带来以下几个优点:

(1) 标签之间的空格在VirtualDOM创建时就被排除,不会带来意外的空白。

(2) 元素的字符串被自动转义,不会容易导致代码注入。

(3) 模块化易实现,从而实现代码共享。

VirtualDOM相对传统DOM操作有以下几个优点:

(1) 资源浪费少、操作简单,处理速度高。

(2) 无需担心兼容性问题。

(3) 通过扩展属性(指令)和数据处理方法(表达式)扩展DOM功能,提高DOM灵活性。

2.3 VirtualDOM树的创建

对复杂的DOM结构,提供一种方便的工具,进而最小化地操作DOM,是VirtualDOM的核心思想。VirtualDOM树是在加载数据时进行创建,在VirtualDOM树创建过程中,需要解决以下关键技术:

(1) 初始化数据initData(data),其中data表示模型的数据。

(2) 判断视图类型。若为子视图,通过get(args)获取VirtualDOM的父容器,并将其子节点转移至VirtualDOM;若为父视图,则获取body容器,转移其子节点。

get(args)定义如下:

get(selector,findAll,pView)

其中,selector表示选择器,findAll表示是否获取所有,默认为false,pView表示的是父对象。

VirtualDOM树具体创建步骤如下:

(1) 创建VirtualDOM根节点;

(2) 检查是否需要加载模板文件,若存在则加载模板文件;

(3) 把模块对应的DOM节点及其子节点转移到VirtualDOM中;

(4) 把模板文件或模板字符串内容统一追加至VirtualDOM中;

(5) 将VirtualDOM绑定到对应模块。

3 VirtualDOM树编译和渲染

VirtualDOM树的编译和渲染是可视化呈现最重要的一步,其速度直接影响应用性能及用户体验。

3.1 编译

编译是利用编译程序从源语言编写的源程序产生目标程序的过程。但本文所提出的编译与C,Java编译不同,本文所提出的编译是将JavaScript代码编译成前端框架能够识别的代码。由上述可知VirtualDOM树的创建步骤,但是前端框架代码并不识别,因此需将VirtualDOM进行编译成前端框架能够识别的代码。

在编译阶段,提供统一编译接口compile,所有的VirtualDOM编译都需要调用接口compile。编译是一个迭代的过程,compile第一步检查VirtualDOM是否已编译,若已编译,则不再编译,只需进行渲染。

在编译阶段,需要解决以下关键技术:

(1) 处理属性值为表达式的指令。使用getAttrsByValue(args)获取属性列表,将带有表达式的属性保存至数组。

(2) 初始化指令集。初始化指令集接口为initViewDirectives(el),el表示视图view。

(3) 遍历待编译的Element的孩子节点,进行文本节点、注释以及元素节点的处理。

VirtualDOM编译流程如图1所示。

图1 VirtualDOM编译流程Fig.1 The compiling process of VirtualDOM

传统的DOM树修改数据之后都需重新编译,不仅浪费资源,还会出现卡顿现象,降低用户体验效果。采用数据驱动模型以及VirtualDOM,实时反映数据的真实变化,简化开发流程,提高开发效率和用户体验度。

3.2 渲染

渲染不仅是将DOM树中的节点进行绘制[10],也是页面进行可视化呈现的最重要的一步,其速度直接影响页面的可视效果。在渲染时,使用DocumentFragment进行缓存操作,使操作元素进行了“离线”处理,减少页面回流和重绘。对一个HTML文件,渲染主要分为以下几步:

(1) 解析HTML并构建VirtualDOM树。浏览器采用自上而下的方式解析HTML,在解析的过程中构建VirtualDOM树。

(2) 将CSS样式应用至VirtualDOM节点。

(3) 布局。布局是一个递归的过程,从根节点开始,递归遍历子节点,并计算每个节点的大小和位置信息。

(4) 绘制。将树绘制在显示屏上。对于每个节点,绘制顺序如下:①背景颜色;②背景图片;③边框;④子节点;⑤轮廓。

不同的渲染引擎,其渲染流程不同,以Webkit为例,其主要过程如图2所示。

图2 Webkit渲染主要过程Fig.2 The main process of webkit rendering

render(container,data)是渲染提供的接口,其中container表示容器,data是数据。在渲染VirtualDOM过程中,需解决以下几个问题:

(1) 判断视图是否存在。若不存在,调用getView(args)获取视图。

(2) 判断是否可以找到视图。若找不到视图,直接返回false,不再进行VirtualDOM的渲染。

(3) 若视图存在,判断其孩子节点的长度是否为0(为0表示没有被渲染)。若为0,克隆VirtualDOM,调用renderDOM(args)将克隆后的所有节点渲染至视图和所有的子节点复制到视图,并设置已渲染的标志。若孩子节点不为0,则从视图开始渲染,即发生变化的数据对象对应的DOM节点及其孩子节点。数据发生变化主要有两种情况:①表达式计算;②指令值发生变化。render渲染流程如图3所示。

4 实验与分析

4.1 实验方案

为验证基于数据驱动模型的VirtualDOM树构建方法的高效性,实验基于传统DOM操作与基于数据驱动模型的VirtualDOM树的构建,并通过不同的DOM节点数,对页面的代码行和编译、渲染速度进行统计,对比它们的差异。实验中使用的2款不同渲染引擎的测试浏览器详细配置见表1。

表1 测试浏览器配置Table 1 The settings of testing browser

图3 VirtualDOM渲染流程Fig.3 The rendering process of VirtualDOM

代码行:实现相同的应用和效果,代码行越少,开发者需要做的工作越少,开发速度越快。

编译和渲染速度:在不同开发模式下,对于相同的数据源,相同页面数据编译和渲染完成所需要的时间。速度越快,用户体验感越好。

在验证过程中,实现了注册(register)、商品列表(commodity)的页面。为排除网络因素对应用性能表现的影响,实验过程中所用的数据均为本地JSON[11]格式数据,图片和文字信息均保存在本地。图4、图5是应用运行在Chrome上的效果截图,其中图4是注册页面,图5是商品列表页面。

4.2 实验结果分析

图6是实现2个页面,采用不同开发模式,开发者需要实现的javaScript代码行数,只包括开发时需要开发者自己编写的代码,不包含基础库的引用。

图4 注册页面运行效果Fig.4 The running effect of registration page

图5 商品列表页面运行效果Fig.5 The running effect of commodity page

图6 开发代码量统计Fig.6 The statistics of development code

从图6可以看出,基于数据驱动模型,开发者需要实现的代码量均比原生javaScript少。主要原因在于基于数据驱动模型开发的应用可以扩展DOM属性和数据处理方法,提高DOM节点灵活性。对于注册页面,需要大量的验证工作,比如邮箱、电话等。使用validity指令可对其进行直接校验,无需复杂的javaScript代码进行选择并操作。在商品列表页面,使用repeat指令对数据进行循环,而无需使用for,forEach等,减少javaScript代码量,提高开发效率。

图7-图9显示了传统DOM和基于数据驱动模型的VirtualDOM树构建两种模式下开发的应用,运行在Chrome,加载不同数据量的页面,第一次加载、修改一条数据、修改全部数据时渲染时间的累积统计对比,数据量分别为50条、100条、500条和1 000条。

图7 第一次加载时间统计Fig.7 The time statistics of first loading

图8 修改一条数据时间统计Fig.8 The time statistics of modifying a piece of data

图9 数据全部修改时间统计Fig.9 The time statistics of modifying all of data

从图中可以看出,基于数据驱动模型的VirtualDOM树构建方法搭建的应用,其渲染时间比原生DOM渲染时间短,其原因是在第一次加载时,VirtualDOM的执行在javaScript引擎中,开销较小;修改数据时,使用数据驱动模型,将复杂的逻辑转移至数据,控制其复杂度,实时反映数据的真实变化。基于原生的应用,每次进行数据修改时,都需要进行选择、绑定事件、数据处理等步骤,所以其修改数据的渲染时间都比较长。图10是基于Chrome,Safari两款不同渲染引擎对原生DOM和基于数据驱动模型的VirtualDOM树构建应用进行渲染所需时间的结果对比,数据量为100条。

图10 基于Chrome,Safari时间统计Fig.10 The time statistics based on Chrome and Safari

从图10可以看出,基于同一种方法开发的应用,在不同渲染引擎的浏览器上运行,页面的渲染所需时间不同,即浏览器本事的渲染引擎性能对应用性能有影响。

根据上述实验可以得出以下两点:第一,实现相同的功能,基于数据驱动模型的VirtualDOM树的构建方法的开发代码量比原生应用少;第二,在相同配置的设备下,基于数据驱动模型的VirtualDOM树构建方法的编译和渲染速度比原生DOM快。在数据量较小的情况下,两者的差别较小。随着数据量的增加,两者之间的差距逐渐增大。

5 结论

为降低Web应用开发难度、提高开发效率,本文提出一种基于数据驱动模型的VirtualDOM树的构建方法。为实现数据双向绑定,采用数据驱动模型,以实现实时显示数据真实变化。采用轻量级JavaScript对象——VirtualDOM模拟真实DOM,提高页面编译和渲染速度,加快开发速度,缩短项目周期。通过扩展DOM属性和数据处理方法,扩展DOM功能,提高DOM节点灵活性。实验结果表明,与传统DOM树相比,基于数据模型的VirtualDOM构建方法,其渲染速度更快、应用性能更高。但是VirtualDOM的执行在JavaScript引擎中会占用部分内存,因此,优化VirtualDOM对内存的占用是下一步研究的重点。

[1]SHAHZAD F. Modern and responsive mobile-enabled web applications [J]. Procedia Computer Science, 2017, 110:410-415.

[2]KNOTT S D, LAIRD J A, WALTERS R J. Dynamic rendering of a document object model, EP2642718[P]. 2013.

[3]FROLIN S O, GUANPENG L, KARTHIK P,et al. Automatic fault localization for client-side JavaScript [J]. Softw. Test. Verif. Reliab.,2016,26(1):28-30.

[4]李景. 基于DOM树信息抽取的移动网站开发研究[D]. 山东青岛:中国海洋大学, 2011.

[5]丁宝琼, 谢远平, 吴琼. 基于改进DOM树的网页去噪声方法[J]. 计算机应用, 2009, 29(b06):175-177.

[6]罗明宇, 凌捷. 基于DOM树序列值比对的SQL注入漏洞检测[J]. 计算机工程与设计, 2015,(2):350-354.

[7]LIJUAN HUANG. Analysis on e-consumers’ purchasing behavior based on data-driving model[J]. Journal of Networks, 2011, 6(12):1713-1718.

[8]HAFIZ M, HASAN S, KING Z, et al. Growing a language: An empirical study on how (and why) developers use some recently-introduced and/or recently-evolving JavaScript features[J]. Journal of Systems & Software, 2016, 121:191-208.

[9]余启洋, 桑楠, 郭文生. 嵌入式浏览器JavaScript引擎的研究与设计[J]. 计算机应用与软件, 2014,(5):251-255.

[10] KIM D, LEE C, LEE S, et al. Parallelized sub-resource loading for web rendering engine[J]. Journal of Systems Architecture, 2013, 59(9):785-793.

[11] 高静, 段会川. JSON数据传输效率研究[J]. 计算机工程与设计, 2011, 32(7):2267-2270.

猜你喜欢
视图代码页面
刷新生活的页面
答案
让Word同时拥有横向页和纵向页
创世代码
创世代码
创世代码
创世代码
视图
Y—20重型运输机多视图
SA2型76毫米车载高炮多视图