美文网首页
1.对象劫持

1.对象劫持

作者: 尘埃落定_Y | 来源:发表于2020-03-24 17:52 被阅读0次

上一篇: 简单的准备工作

为了更加有代入感,我们直接就在 src/index.js 下按照平时项目工程的写法开始;

mockVue.png

在 source/vue/index.js

import { initState } from './observer';
// 构造函数
function Vue(options) {
  this._init(options);
};
Vue.prototype._init = function(options) {
  let vm = this;
  // $options 表示 new Vue的时候传入的参数
  vm.$options = options;
  initState(vm);
}
export default Vue;

接下来新建一个 observer 文件夹, 再写一个 initState 的函数来完成初始化;

mkdir observer
cd observer 
new-item index.js
// observer/index.js
import Observer from './observer';

export function initState(vm) {
  let opts = vm.$options;
  if (opts.data) { 
  // 初始化 data 属性
    initData(vm)
  }
};

export function observer(data) {
  if (typeof data !== 'object' || data == null) {
    return;
  }
  return new Observer(data);
}

function initData(vm) {
  let data = vm.$options.data;
  // 有可能 是函数,有可能是对象
  data = vm._data = typeof data === 'function' ? data.call(vm) : data || {};
  observer(vm._data);
};

走到这一步,很接近核心了,接下来就是 基于 Object.defineProperty
实现响应式数据;

// Powershell 
new-item observer.js
// observer/observer.js

import { observer } from './index';
export function defineReactive(data, key, value) {
  /**
    这里是闭包的实际应用, value 的引用在外部使用, 
    不会被收回,每次更新数据都从 defineReactive 的作用域 VO 里面获取value
   */ 
  observer(value);  // 有可能当前value 是一个对象, 所以再调用一次 observer函数
  return Object.defineProperty(data, key, {
    get () {
      return value;
    },
    set (newValue) {
      if (newValue === value) return;
      value = newValue;
    }
  })
}


class Observer {
  constructor(data) {
    this.walk(data)
  }

  walk(data) {
  // 遍历传入的 对象, 循环调用 defineReactive;
    let keys = Object.keys(data);
    for (let i = 0; i < keys.length; i++) {
      let key = keys[i]
      defineReactive(data, key, data[key]);
    }
  }
};


export default Observer;

相关文章

网友评论

      本文标题:1.对象劫持

      本文链接:https://www.haomeiwen.com/subject/vnswyhtx.html