赞
踩
1. 创建一个index.js作为入口文件,创建一个Vue函数,并且抽离初始化文件进行模块化
import { initMixin } from "./init"; // 初始化 抽离模块化
function Vue(options) {
// new Vue 时是进行初始化
this._init(options);
}
initMixin(Vue);
export default Vue;
2. 创建初始化文件init.js,在Vue函数的实例上创建一个_init方法进行初始化状态
import { initStates } from "./initState";
export function initMixin(Vue) {
Vue.prototype._init = function (options) {
let vm = this;
vm.$options = options;
// 初始化状态
initStates(vm);
};
}
3. 创建初始化状态文件initState.js,在这里面写所有的初始化方法(data,props,watch,methods…)
import { observer } from "./observer/index"; export function initStates(vm) { let opts = vm.$options; if (opts.data) { initData(vm); } if (opts.props) { initProps(vm); } if (opts.watch) { initWatch(vm); } if (opts.computed) { initComputed(vm); } if (opts.methods) { initMethods(vm); } } //! Vue2 对data进行初始化 function initData(vm) { //> 会有两种初始化方式 1. 对象 2. 函数 let data = vm.$options.data; data = vm._data = typeof data === "function" ? data.call(vm) : data; //> 对数据data进行劫持 observer(data); } function initProps() {} function initWatch() {} function initComputed() {} function initMethods() {}
4. 创建一个文件夹observer里面的index.js,在这里面进行数据的劫持和发布订阅模式
export function observer(data) { //> 判断data是否是对象或者空 if (typeof data != "object" || data == null) { return data; } //> 1. 对象通过一个类 return new Observer(data); } //> vue2 进行劫持是通过Object.defineProperty() //! 缺点:只能是对象中的一个属性进行劫持 懒劫持 class Observer { constructor(value) { //> 进行遍历 让每一个属性都劫持到 this.walk(value); } walk(data) { //> keys 是对象所有的属性 let keys = Object.keys(data); for (let i = 0; i < keys.length; i++) { //> 对我们每一个属性进行劫持 const key = keys[i]; const value = data[key]; // console.log(value); defineReactive(data, key, value); } } } //> 对对象属性进行劫持 function defineReactive(data, key, value) { observer(value); //! 进行递归 ,深层次的劫持 Object.defineProperty(data, key, { get() { return value; }, set(newValue) { if (newValue == value) return; observer(newValue); // 如果用户设置的值是对象,也要进行劫持 value = newValue; }, }); }
总结
1. 需要多data数据进行判断,是对象还是函数,如果是函数就要改变this执行为vm
2. Object.defineProperty 有缺点,只能对对象中的一个属性进行劫持 所以进行遍历
3. 递归 将深层次的数据进行get set劫持
运行
为了方便打印查看是否进行数据劫持 在vm实例上添加_data属性存放data数据
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。