入口文件 index.js
import { initMixin } from "./init";
function Vue(options){
console.log(options);
this._init(options)//当用户new vue时 就调用init方法进行vue的初始化方法
}
// 可以拆分逻辑到不同的文件中,更利于代码维护 模块化的概念
initMixin(Vue)
export default Vue
入口文件初始化项目
初始化项目文件 init.js
import { initState } from "./state"
export function initMixin(Vue){
Vue.prototype._init = function(options){
console.log('options',options)
let vm =this
vm.$options = options//实例上有个 options 表示用户传入的所有属性
initState(vm)//初始化状态
// initLifeCycle()//初始化生命周期
}
}
数据处理文件 state.js
import { observe } from "./observe/index";
// VUE 的数据 data watch computed
export function initState(vm) {
console.log("initState",vm)
// 将所有数据都定义在vm属性上,并且后续更改 需要触发试图更新
const opts = vm.$options; //获取用户属性
if (opts.data) {
//数据的初始化
initData(vm);
}
if (opts.methods) {
}
if (opts.computed) {
}
if (opts.watch) {
}
}
function proxy(vm, source, key) {
Object.defineProperty(vm, key, {
get() {
return vm[source][key];
},
set(newValue) {
vm[source][key] = newValue;
},
});
}
function initData(vm) {
let data = vm.$options.data;
// 对data类型进行判断 如果式函数 获取函数返回值作为对象
data = vm._data = typeof data === "function" ? data.call(vm) : data;
// 观测数据
// 通过vm._data获取劫持后的数据 用户就可以拿到 _data
console.log("data",data)
// 将_data中的数据全部放到vm上
for (const key in data) {
proxy(vm, "_data", key);
}
observe(data);
}
数据代理
使用 object.defineProperty代理数据,可以直接通过this访问,而不需要this._data访问数据
observe/index.js文件 实现数据的观测
class Observer {
constructor(value) {
//需要对这个value属性重新定义
this.walk(value);
}
walk(data) {
// 将对象中的所有key,重新用defineProperty 定义成响应式的
console.log("walkData",data)
Object.keys(data).forEach((key) => {
defineReactive(data, key, data[key]);
});
}
}
export function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
get() {
console.log("get");
return value;
},
set(newValue) {
console.log("set");
if (newValue === value) {
return;
}
value = newValue;
},
});
}
export function observe(data) {
console.log(data, "============");
// 只对对象类型进行观测 非对象无法关测
if (typeof data !== "object" || data == null) {
return;
}
// 通过类来实现对对象的观测,类可以方便扩展,会产生实例
return new Observer(data);
}
注解
export function observe(data) {
console.log(data, "============");
// 只对对象类型进行观测 非对象无法关测
if (typeof data !== "object" || data == null) {
return;
}
// 通过类来实现对对象的观测,类可以方便扩展,会产生实例
return new Observer(data);
}
观测数据时,要先判断观测的数据是不是 对象 ,如果不是对象就停止观测
是对象就 调用 Obsever类进行数据劫持
class Observer {
constructor(value) {
//需要对这个value属性重新定义
this.walk(value);
}
walk(data) {
// 将对象中的所有key,重新用defineProperty 定义成响应式的
console.log("walkData",data)
Object.keys(data).forEach((key) => {
defineReactive(data, key, data[key]);
});
}
}
使用 Observer类实现数据的观测,调用definerReactive实现数据的劫持
注解
Object.keys 处理对象,返回以对象的属性键值组成的数组(不包括原型上的属性键值)
export function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
get() {
console.log("get");
return value;
},
set(newValue) {
console.log("set");
if (newValue === value) {
return;
}
value = newValue;
},
});
}
Object.defineProperty 用于数据劫持
get和set ,
get用户读取数据,
set 用于设置数据,在数据改边时触发,可用于更新视图