Vue 源码
你想要的 vue 源码分析 · 01
vue 源码学习第一天 vue 内部运行机制 new Vue()后有几个过程 初始化和挂载 初始化 初始化生命周期,事件,props,methods,data,computed 和 watch 等,最重要是通过 设置 和 来实现响应式和依赖收集。 挂载 $mount 会挂载所有组件,如果存在 template,需要进行编译 编译 编译分为三个过程 1.parse 2.optimize 3.gene…
vue 源码学习第一天 vue 内部运行机制 new Vue()后有几个过程 初始化和挂载 初始化 初始化生命周期,事件,props,methods,data,computed 和 watch 等,最重要是通过 设置 和 来实现响应式和依赖收集。 挂载 $mount 会挂载所有组件,如果存在 template,需要进行编译 编译 编译分为三个过程 1.parse 2.optimize 3.gene…
图片来自[染陌同学](https://github.com/answershuto)

初始化生命周期,事件,props,methods,data,computed 和 watch 等,最重要是通过
Object.defineObjectProperty设置getter和setter来实现响应式和依赖收集。
$mount 会挂载所有组件,如果存在 template,需要进行编译
编译分为三个过程 1.parse 2.optimize 3.generate
parse 将 template 转成字符串,然后正则匹配指令,如
v-ifv-forclass等,然后生成抽象语法树
标记静态节点,在以后的 update 过程中,diff 算法会跳过静态节点,如果存在
v-ifv-for就不是静态节点
将抽象语法树生成 render function 进而生成 Vnode,Vnode 可以用来模拟虚拟 DOM,虚拟 DOM 本质是 Object,可运行在不同的环境中
虚拟 DOM 是把真实 DOM 抽象成了有着 DOM 属性的对象
更新视图的触发条件是 patch 到了有差异的 Vnode,执行的过程是 setter->Dep->Watcher->patch->视图
vue.js 是通过 Object.defineProperty 来实现响应式系统,Object.defineProperty 有 4 个关键属性,1.
enumerable,属性是否可枚举,默认 false ;2.configurable,属性是否可以被修改或者删除,默认 false ;3.get,获取属性的方法。4.set,设置属性的方法。
new Vue 对象将 data 中的数据进行响应式化,对 data 的属性进行操作,就会触发更新方法,代码如下。
function notify() {
console.log('有内容更新了');
}
function defineData(obj, key, value) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function() {
return value;
},
set: function(newVal) {
if (newVal === value) return;
notify();
}
});
}
function observer(data) {
if (typeof data !== 'object') {
return;
}
Object.keys(data).forEach((key) => {
defineData(data, key, data[key]);
});
}
class Vue {
constructor(options) {
this._data = options.data;
observer(this._data);
}
}
let myVue = new Vue({
data: {
value: 'hello world'
}
});
myVue._data.value = 'nioe world';
为什么要依赖收集
如何实现依赖收集
// 依赖收集的集合
class Dep {
constructor() {
this.collections = [];
}
add(watcher) {
this.collections.push(watcher);
}
notify() {
this.collections.forEach((watcher) => {
watcher.update();
});
}
}
class Watcher {
constructor() {
Dep.self = this;
}
update() {
console.log('更新了');
}
}
function defineData(data, key, value) {
let dep = new Dep();
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function() {
dep.add(Dep.self);
return value;
},
set: function(newValue) {
if (value == newValue) {
return;
}
dep.notify();
}
});
}
function observer(data) {
if (typeof data != 'object') {
return;
}
Object.keys(data).forEach((key) => {
defineData(data, key, data[key]);
});
}
class Vue {
constructor(options) {
this._data = options.data;
observer(this._data);
// 在这里模拟render的过程
new Watcher();
this._data.value = this._data.value;
}
}
let myVue = new Vue({
data: {
value: 'hello world'
}
});
myVue._data.value = 'nice world';
Dep.self = null;
依赖收集的前提条件是 1. 新建一个 Watcher 对象 2. 触发了 get 方法依赖收集主要是get进行依赖收集,set通过观察者更新视图记住一个过程:当读取所需对象的值时会触发 setter 方法(observer 方法会触发 setter 方法),setter->Dep->Watcher->patch->视图class VNode {
constructor(tag, data, children, text, elm) {
/*当前节点的标签名*/
this.tag = tag;
/*当前节点的一些数据信息,比如props、attrs等数据*/
this.data = data;
/*当前节点的子节点,是一个数组*/
this.children = children;
/*当前节点的文本*/
this.text = text;
/*当前虚拟节点对应的真实dom节点*/
this.elm = elm;
}
}
console.log(
new VNode(
'span',
{
/* 指令集合数组 */
directives: [
{
/* v-show指令 */
rawName: 'v-show',
expression: 'isShow',
name: 'show',
value: true
}
],
/* 静态class */
staticClass: 'demo'
},
[new VNode(undefined, undefined, undefined, 'This is a span.')]
)
);
今天学习了 vue 的初始化和挂载、vue 是如何编译的、响应式系统的基本原理,虚拟 DOM 是如何生成的、响应式系统的依赖收集追踪原理、更新视图 patch 的比较算法
暂无评论
确认操作
请再次确认编辑图片
待上传图片 (剩余 0 张)
项目详情
确认评论邮箱
邀请制评论