一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
Vue全家桶的系统学习,其中包括Vue源码分析、Vue-Router的使用和原理、Vuex的用法和原理、Vue-ssr、如何进行单元测试 和 一些常见的Vue面试题。
参数解析
我们都知道,Vue中有一种特殊的模板语法 {{}}
, Mustache语法,也就是我们经常说的 胡子语法。
<div id="app">
<div>{{name}}</div>
<span>{{age}}</span>
</div>
<script src="../dist/umd/vue.js"></script>
<script>
let vm = new Vue({
el: "#app", // 将数据解析到 el 元素上
data() {
return {
name: "MXShang",
age: 25,
};
},
});
</script>
在Vue框架中,数据就被渲染到视图中了。
所以现在我们需要将 模板中的内容 和 数据 进行替换。
数据渲染的几种方式
- 模板引擎 : 模板引擎 的使用方法在我之前的文章中有提到过,感兴趣的可以去了解一下。 其大概思路就是每次渲染时,将模板中的内容拿到,并进行正则匹配与替换。 这样操作会有一个问题,那就是 性能很差。而在
Vue1.0
时,并没有引入 虚拟DOM 的概念,所以它的性能是很差的。 - 虚拟DOM:数据变化后,比较虚拟DOM的差异,最后更新需要改变的地方。
核心思路就是,将模板变成 JS语法,并通过 JS语法 生成 虚拟DOM。
从一种东西转换成另一种东西,比如 语法间的转换、css的压缩 等等。我们都需要先将其变成 语法树 ,然后再重新组装成新的代码。
在Vue中,我们就需要将 template 转变成 render函数 。
let vm = new Vue({
el: "#app",
template: "<div>hello</div>", // template属性可以将内容渲染在el元素中
render() {
// h 就相当于 createElement
return h("div", {});
},
});
数据挂载
首先,我们在初始化的时候,要先判断是否传入了 el属性。
Vue.prototype._init = function (options) {
const vm = this;
vm.$options = options;
initState(vm);
// 实现数据挂载
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
}
如果传入了 el属性,则将其传入 $mount
函数中。
(注:所以我们在实际项目中,使用 el
挂载和在全局中使用 vm.$mount
挂载效果是一样的。)
$mount函数
$mount
函数其实就是一个 挂载函数,它用来判断当前实例中是否包含 el
、template
和 render
函数 等。
-
在Vue原型上添加一个
$mount
方法,将el
传入。Vue.prototype.$mount = function (el) { // ... }
-
获取
el
对应的Dom元素。Vue.prototype.$mount = function (el) { const vm = this; const options = vm.$options; // 将options也提取出来,因为后面会频繁使用 el = document.querySelector(el); }
-
判断是否传入了
render
和template
等属性,随后通过compileToFunctions
函数,将 template 编译成 render函数。Vue.prototype.$mount = function (el) { // ... // 如果没有render方法 if (!options.render) { let template = options.template; // 如果没有模板但是有el if (!template && el) { template = el.outerHTML; } const render= compileToFunctions(template); options.render = render; // 导出最终的 render 方法 } }
compileToFunctions
函数 其实就是将传入的 template
转变成对应的 AST语法树 ,并生成对应的代码,然后再生成 render函数 。
我们现在需要在目录中新建一个模块 compiler
。
|-- src
|-- index.js
|-- init.js
|-- state.js
|-- util.js
|-- compiler
| |-- index.js
|-- observer
|-- array.js
|-- index.js
这个模块就是用来对 compileToFunctions
函数 进行封装与完善的。
// compiler/index.js
export function compileToFunctions(template) {
console.log(template);
}
在后续的文章中,我们会详细介绍一下如何生成 AST语法树。
本篇文章由 莫小尚 创作,文章中如有任何问题和纰漏,欢迎您的指正与交流。 您也可以关注我的 个人站点、博客园 和 掘金,我会在文章产出后同步上传到这些平台上。 最后感谢您的支持!