✨Vue源码-简单的模板解析
type
status
date
slug
summary
tags
category
icon
password
Status
Vue 主要在
<template>
标签中编写 DOM 结构,除了静态的 html 标签,还包含指令、插槽、组件、表达式等更丰富的内容。这期简单解析一下 Vue 中模板的原理。模板语法
模板语法允许我们声明式地将数据绑定到对应 DOM 节点上,在渲染时,JavaScript 会将变量值或计算出的表达式结果替换掉声明部分。较为常见的模板语法有
mustcache
风格的{{}}
以及DSL
风格的html dsl
等。以
mustcache
为例,比较简单的模板语法可以使用正则匹配的方式,替换掉{{}}
,通过new Function
创建一个render
函数传参,实现文本插值。对循环等指令,同样可以通过这样解析替换实现,这里未给出。Vue1 最核心的实现就是基于这种简单地处理 token 流实现,然而对于比较复杂的渲染,解析的次数会逐渐变多,带来性能问题。
于是很快诞生的 Vue2,引入了虚拟 DOM,即将真实 DOM 解析成 AST(
Abstract Syntax Tree
),方便后续对模板进行处理,减少了多次解析字符串带来的性能消耗,同时将HTML
变成一棵树的数据结构之后更加方便于遍历。例如下面给出的这段 HTML 代码:
解析成的最简单的 AST:(parent 为父节点引用,暂不列出)
基于 AST 的模板语法需要解析 HTML 成为 AST,然后将 AST 转化为字符串,将字符串作为函数执行,这个过程依旧需要用到 Function,下边的例子只是借助了 JavaScript 取得 DOM 结构生成 AST,没有自行解析 HTML。
虽然看起来最后都需要使用
Function
去处理字符串,而得到 AST 后还需要解析HTML
然后再拼接字符串,增加了计算的时间,但是如果仅仅是完全基于处理字符串的方式实现的模板语法,在数据进行变更时都需要进行render
,每次render
的时候都需要重新渲染整个 DOM。虽然在上边的简单实现中
AST
也是重新渲染了整个模版,但目前主流的框架例如Vue
就是基于AST
的方式,首先解析template
为AST
,然后对于AST
进行静态节点标记,通过重用已标记静态的节点跳过比对,从而进行渲染优化,然后生成虚拟 DOM。当数据进行变更时虚拟 DOM 会进行diff
算法的比对,找到数据有变更的节点,然后进行最小化渲染,这样就不需要在数据变更时将整个模板进行渲染,从而增加了渲染的效率。- Twikoo