专栏首页coding个人笔记vue数据监听和劫持

vue数据监听和劫持

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.js
function 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.js
function 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.js
let 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的数据响应有很大帮助,复制到编辑器里,静下来理一理,你会发现顿悟一样。

(完)

本文分享自微信公众号 - coding个人笔记(gh_2ce38b49dae1),作者:wade

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Vue数据不渲染问题

    使用vue开发项目的时候,几乎都会遇到一个问题,数据改变了,但是页面没有渲染。这种情况下一般都是数组和json才会发生。

    wade
  • 图片预加载和懒加载

    对于前端性能来说,图片是一个过不去的坎,又想能页面美观,又想页面响应速度快,那么这时候就有了两个技术,图片懒加载和预加载。在这边我只介绍一些方法和原理,不具体把...

    wade
  • ES6之变量的解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。解构赋值在一些场景下还是很有用的。

    wade
  • jquery---data

    elem.data(object);//object为{key:value};

    sucl
  • bootstrap table x-editable select2——带图标的选择

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

    hotqin888
  • 通过空气质量指数AQI学习统计分析并进行预测(上)

    AQI(空气质量指数),用来衡量空气清洁或者污染的程度。值越小,表示空气质量越好。近年来,因为环境问题,空气质量也越来越受到人们的重视。

    朱小五
  • jquery mobile 移动web(1)

    轻量级框架jQuery Mobile   所需文件     <link rel="stylesheet" href="jquery.mobile-1.1.2/...

    用户1197315
  • 采用HTML5之"data-"机制自由提供数据

    周末总是过得很快,又到了跟代码亲密接触的日子,我在北京向各位问好,今天我分享一点关于前端的东西,HTML5之标签"data-*"自定义属性的值传递。     ...

    赵小忠
  • 微信小程序教学第三章(含视频):小程序中级实战教程:列表-页面逻辑处理

    § 页面逻辑处理 本文配套视频地址: https://v.qq.com/x/page/n0554dndrez.html 开始前请把 ch3-2 分支中...

    iKcamp
  • 稀疏矩阵及其实现

    李志伟

扫码关注云+社区

领取腾讯云代金券