Vue2源码解析实现—Vue响应式实现(对data中对象的属性劫持)

文章详细介绍了Vue2如何实现数据响应式,主要涉及数据劫持通过Object.defineProperty,以及初始化过程,包括入口文件、初始化状态文件和Observer类的使用,实现了对data的深度遍历和劫持,确保视图能根据数据变化实时更新。
摘要由CSDN通过智能技术生成

Vue2源码解析实现

Vue响应式实现

  • Vue响应式原理
    vue 实现数据响应式 ,是通过数据劫持侦测数据变化,发布订阅模式进行依赖收集与视图更新,Observe实现数据劫持,递归给对象属性,绑定setter和getter函数
  • 实现机制
    Vue的双向绑定实现机制核心:
    • 依赖于Object.defineProperty()实现数据劫持
    • 订阅模式
  • Vue2源码实现 —— 对data中对象的属性劫持

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数据
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龟中的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值