vue数据监听和劫持
来源:     阅读:542
云上智慧
发布于 2020-04-24 19:44
查看主页

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
免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境 服务器应用
相关推荐
书籍:Daniel Arbuckle's Mastering Python - 2017
企业有没有必要申请EV证书?
Dubbo + Zipkin + Brave实现全链路追踪
OkHttp源码之socket连接池
95年程序员高调面试被HR直接pass,网友:没毛病,家里不缺钱!
首页
搜索
订单
购物车
我的