vue数据监听和劫持

作者 : 开心源码 本文共2358个字,预计阅读时间需要6分钟 发布时间: 2022-05-13 共192人阅读

vue对数据的监听都知道是通过Object.defineProperty,今天简单把过程捋了一下,弄清楚vue对数据的解决。

//index.js//公告vue构造函数,进行初始化function Vue(options) { this._init(options);}Vue.prototype._init = function (options) { //定义一个vm let vm = this; vm.$options = options; //初始化 initState(vm);}//observe/index.jsfunction initState(vm) { //初始化props methods data computed watch let opts = vm.$options; if(opts.data){  initData(vm); } // if(opts.watch){ //   initWatch(opts.watch); // }}function initData(vm) { let data = vm.$options.data; //挂载data到vm_data,不改变原data data = vm._data = typeof data === 'function' ? data.call(vm) : data || {}; //代理商data上的数据到_data for (let key in data) {  proxy(vm, '_data', key) } //数据进行观察 observe(vm._data);}function proxy(vm, source, key) { Object.defineProperty(vm, key, {  get(){   return vm[source][key];  },  set(newValue){   vm[source][key] = newValue;  } })}function observe(data) { //假如不是对象,就不进行监听{a:5},监听了a,不监听5 if(typeof data !== 'object' || data === null){  return } return new Observer(data);}//observe/observer.jsfunction Observer(data) { //假如是数组另外解决 if(Array.isArray(data)){  //劫持数组方法  data.__proto__ = arrrayMethods;  //数组每一项进行监听  observerArray(data); }else{  //对象进行监听  this.walk(data); }}Observer.prototype.walk = function (data) { let keys = Object.keys(data); for (let i = 0; i < keys.length; i++) {  defineReactive(data, keys[i], data[keys[i]]); }}//核心代码,对对象进行监听function defineReactive(data, key, value) { //判断,假如对象里面嵌套对象,递归监听 //vue一个性能痛点,vue3用proxy改进,proxy兼容会有点问题 observe(value); //核心 Object.defineProperty(data, key, {  get(){   console.log('get---' + key + '---' + value);   return value;  },  set(newValue){   console.log('set---' + key + '---' + value);   if(value === newValue){    return   }   value = newValue;  } })}//observe/array.jslet arrayProto = Array.prototype;//拷贝数组方法let arrrayMethods = Object.create(arrayProto);let changeMethods = ['push', 'pop', 'unshift', 'shift', 'sort', 'reverse', 'splice'];changeMethods.forEach(method => { //对七个会改变原数组的方法进行劫持,切片编程 arrrayMethods[method] = function (...args) {  let inserted;  switch (method) {   case 'push':   case 'unshift':    inserted = args;    break;   case 'splice':    inserted = args.splice(2);    break;   default:    break;  };  //对于新添加的数组项进行监听  if(inserted) observerArray(inserted);  //最终还是调用数组原方法  return arrayProto[method].apply(this, args); }})function observerArray(inserted) { for (let i = 0; i < inserted.length; i++) {  observe(inserted[i]); }}

而后即可以去调用:

let vm = new Vue({ data(){  return {   msg: 'hello',   obj: {a: 10},   arr: [1, 2, 3]  } }, methods:{},})console.log(vm.$options);

这边只是很简单的理了一下,源码大概也能找到这些方法,源码当然更复杂,把方法都写到一起了,假如是npm包的话是通过import和export导入导出,这边也有把划分的写了一下。

真的觉得好好了解一下,对于vue的数据响应有很大帮助,复制到编辑器里,静下来理一理,你会发现顿悟一样。

image

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » vue数据监听和劫持

发表回复