手写响应式数据系统底层、手写模板编译系统底层、手写虚拟DOM和diff算法底层……拒绝纸上谈兵,手撸一个自己的Vue框架!
源码重点:模板技术、数据劫持、虚拟节点、最小量更新、抽象语法树等等
Vue源码解析之mustache模板引擎
1.什么是模板引擎
2.mustache基本使用
3.mustache的底层核心机制
4.手写一个mustache库
5.总结
1.什么是模板引擎

历史上曾经出现的数据转为视图的方案
- 纯DOM法:原生JS创建DOM节点,以及样式、类名、DOM结构关系,然后append到页面上(
document.createElement('ul').appendChild('li').className().style.setProperty) - 数组jion法:遍历数组,然后用字符串jion方法添加到innerHtml里
- ES6模板字符串,支持换行,
${var}支持变量 - 模板引擎:mustache.js 是一个简单强大的 JavaScript 模板引擎,使用它可以简化在 js 代码中的 html 编写。
2.mustache基本使用
mustache是最早的模板引擎,vue只是引用了语法,引入mustache库才能使用
1.cdn引入(https://cdn.bootcdn.net/ajax/libs/mustache.js/4.2.0/mustache.js)
2.模板、数据、绑定、渲染四个步骤
// 模板 {{#arr}} {{age}}{{.}}{{/arr}}
var templateStr = document.getElementById('my-tem').innerHTML
// 数据
const data = {
arr: [],
}
// 绑定
var domStr = mustache.render(templateStr, data)
// 渲染
document.getElementById('app').innerHTML= domStr
3.mustache的底层核心机制

渲染过程
4.手写一个mustache库
具体实现的步骤:
- Scanner类:储存templateStr,pos,tail,实现过指定字符串并返回内容的函数
- 生成tokens:生成scan实例,遍历模板字符串,使用scan{{拿到text的内容并存进tokens中;使用}}拿到要渲染的内容进行分类:如果是#开头说明要循环,存入#类型的数组,值为数组的key;如果是/开头存入/类型,值为数组;其他情况则是data的key,存入name类型
- tokens数组的折叠:维护一个栈sections和数组指针current,添加内容都在栈顶添加(栈中如果没有元素则代表是根数组tokens数组),遇到token项类型为'#',则压栈(包括sections和当前数组),开辟第三个位置数组,并将current指向栈顶元素,遇到token项类型为'/',则直接出栈,并考虑current是否指向根数组;其他情况则为name或者text的token直接存至current数组中去。
- tokens和data结合生成HTML:对tokens数组进行每一项类型检查:如果为text,直接加进htmlStr中去;如果为name,将数据值加入htmlStr;如果为#,则需要进行递归调用,将这一项的子tokens和封装了.属性的子对象传入参数。
- 最后返回整个htmlStr,传入模板字符串与数据,在html文件中进行调用
var domstr = MY_templateEngine.render(str, data)
document.getElementById('app').innerHTML=(domstr)
export default function render(templateStr,Data){
//生成tokens
let tokens = genTokens(templateStr);
//生成HTML
let htmlStr = renderTemplate(tokens,Data);
return htmlStr;
}
function genTokens(templateStr){
//生成初始tokens
let initTokens = initTokens(templateStr);
//生成折叠后的tokens
let resultTokens = nestTokens(initTokens);
return resultTokens;
}
function initTokens(templateStr){
let initTokens = [];
let pos = 0;
return initTokens;
}
function nestTokens(initTokens){
let resultTokens = [];
return resultTokens;
}
function renderTemplate(tokens,Data){
let htmlStr = '';
return htmlStr;
}
5.总结:
未涉及到vue的模板指令v-for,v-if等等,但它们都是基于mustache,都是将数据转成视图。
Mustache底层太美了!tokens的意义也不言自明了。如果没有token,那么数组的循环形式,就很难处理。我们通过本课,确实学到了很多,视野面变得更广,感觉肚子里的东西更多了;
在Mustache源码中,还有Context类和Writer类,在我们的代码演示中, 都将它们进行了简化,但是不影响主干功能的实现。我们的这个“简化版本的”代码非常值得大家进行手写,你会受益良多的!当然,如果有精力,可以再研究透彻这个“简化版本的”代码后,自己对Mustache原包进行学习;