vue2源码-二、对象响应式原理
对象响应式原理
初始化操作,扩展
init方法:// index.js function Vue(options) { this._init(options) } initMixin(Vue) // 扩展了init方法 export default Vue在
initMinin方法中,扩展了init方法。以下获用户的
option。// init.js import { initState } from './state.js' // 就是给Vue增加init方法的 export function initMixin(Vue) { // 初始化操作 Vue.prototype._init = function (options) { // vue vm.$options就是获取用户的配置 // 使用vue的时候$是vue定义的,而且再实例上 const vm = this vm.$options = options // 将用户的选项挂载到实例上 // 初始化状态 initState(vm) } }核心模块
observe:数据监测data数据的响应式原理:通过
Object.definProperty重写data上的所有属性。调用的
initState方法,这个方法需要对数据进行劫持。import { observe } from './observe/index' // 主函数 // 1. 封装主函数,如果存在data属性,则进行初始化数据 export function initState(vm) { const opts = vm.$options // options不是空 if (opts.data) { initData(vm) } } // vm._data.name 变成vm.name 代理 function proxy(vm, target, key) { Object.defineProperty(vm, key, { get() { return vm[target][key] }, set(newValue) { vm[target][key] = newValue }, }) } // 2.初始化数据 function initData(vm) { let data = vm.$options.data // 可能是函数和对象 // data可能是函数也可能是对象,函数需要进行this绑定。 data = typeof data === 'function' ? data.call(vm) : data // data是用户返回的对象 vm._data = data // 将返回的对象放到_data // 对数组进行劫持vue2里采用一个api defineProperty // 3.后面会提及 observe(data) // 将vm._data用vm来代理就可以了 for (let key in data) { proxy(vm, '_data', key) } }Obsever类:对对象进行观测。
observe方法:export function observe(data) { // 对这个对象进行劫持 if (typeof data !== "object" || data === null) { return; // 只对对象进行劫持 } // 如果一个对象被劫持过了,那就不需要在劫持了(判断一个对象是否被劫持过,可以添加一个实例,用实例来判断是否被劫持过) return new Observe(data); }这个方法返回了一个输入数据的观测对象。
那返回一个什么样的对象呢?
// 循环对象进行一次劫持 class Observer{ constructor(value){ this.walk() } walk(data) { // 重新定义属性 Object.keys(data).forEach((key) => defineReactive(data, key, data[key])) } } // 属性劫持 // 对对象target,定义属性key,值为value // 使用Object.definProperty重新定义data的属性 export function defineReactive(target, key, value) { observe(value) // 递归对所有的属性进行劫持 Object.defineProperty(target, key, { // 用户取值 get() { console.log('用户设置值00') return value }, // 用户设置值了 set(newValue) { console.log('用户取值了') if (newValue === value) return // 递归,设置了对象 observe(newValue) value = newValue }, }) }

浙公网安备 33010602011771号