前言
对于vue源码的解析 想必 是面试常考的了 对于一个 一年的小白笔者 也是被问到蒙圈 回答的只言片语 现在工作也渐渐稳定 一切向好 趁着脑子还没生锈 一步一步的开始 了解一下 当然了 这里只是第一篇 还会陆陆续续补上 一起加油吧 新时代的打工人。
介绍
<div id="app">
{{ message }}
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作
现在数据和 DOM 已经被建立了关联,所有东西都是响应式的
Vue最大的特点之一就是数据驱动视图,视图更新影响数据/数据更新影响视图 想要实现这个功能 就需要先弄明白 vue对data中的数据 都做了什么操作 本篇主要介绍一下是对对象
怎么操作也就是怎么使用的Object.defineProperty
方法;
Object.defineProperty
如果你不了解的话可以查看MDN关于Object.defineProperty的介绍
let data = {message:"hello word"}
比如我们定义了一个data对象 现在需要把他 变成 可观测的 我们可以 这样改写代码
let data = {}
let message = "hello word"
Object.defineProperty(data, 'message', {
enumerable: true,
configurable: true,
get(){
console.log('读取message')
return message
},
set(newMessage){
console.log('更新message')
message = newMessage
}
})
给属性添加了get
,set
方法 读取触发get()
写入触发set(新值)
读取:data.message --> 读取message
写入:data.message = 'vue' ---> 更新message
这样 一个对象就变的 可读 可写
核心源码
如果我们data中有很多属性 那就去 循环处理
所以可以改写上面的代码
class Observer {
constructor(value) {
this.value = value;
if (Array.isArray(value)) {
console.log("Array");
// 如果是数组需要进行单独处理
} else {
this.walk(value);
}
}
walk(obj) {
const keys = Object.keys(obj);
// 得到健名之后进行循环 调用 defineReactive方法
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i]);
}
}
}
function defineReactive(
obj, // data 数据
key, // 当前执行的健名
val
) {
if (arguments.length === 2) {
val = obj[key];
}
// 调用observe 方法 进行判断是否 深度添加 get()/set()
observe();
// 核心部分
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log(`${key}属性被读取了`);
return val;
},
set: function reactiveSetter(newVal) {
if (val === newVal) {
return;
}
console.log(`${key}属性被修改了`);
val = newVal;
},
});
}
function observe(value) {
// 如果是对象就 递归调用
if (isPlainObject(value)) {
new Observer(value);
}
}
function isPlainObject(value) {
return Object.prototype.toString.call(value) === "[object Object]";
}
let data = {
platform: "掘金",
author: 'Wandou',
date: {
checkTime: "2021-9-3",
},
};
new Observer(data);
这样 最简单的 一个 数据监听 就实现了
源码:/src/core/observer/index.js
如果 你有精力 可以查看 一下源码 你会发现 上面我们改写的代码 跟 vue源码的执行逻辑 是一样的
这里只是一个示例 还有 添加Dep队列 判断是否已经进行监听 ....
总结
感谢您能读到最后!
一起加油吧~