vue2.x数组劫持原理的实现


Posted in Javascript onApril 19, 2020

接上篇Vue2.x 对象劫持,继续来写数组劫持

实现原理:
1 重新定义原生数组方法push unshift shift pop splice sort reverse 因为这些方法可以修改原数组。
2 拿到原生数组方法 Object.create(Array.prototype)
3 AOP拦截,再执行重写数组方法前,先执行原生数组方法

核心监听Observer代码

// 把data中的数据 都使用Object.defineProperty重新定义 es5
// Object.defineProperty 不能兼容ie8 及以下 vue2 无法兼容ie8版本
import {arrayMethods} from './array.js'
import {
  isObject,def
} from '../util/index'
// 后续我可以知道它是不是一个已经观察了的数据 __ob__
class Observer{
  constructor(value){ // 仅仅是初始化的操作
    // vue如果数据的层次过多 需要递归的去解析对象中的属性,依次增加set和get方法
    // value.__ob__ = this; // 我给每一个监控过的对象都增加一个__ob__属性
    def(value,'__ob__',this);
    if(Array.isArray(value)){
      // 如果是数组的话并不会对索引进行观测 因为会导致性能问题
      // 前端开发中很少很少 去操作索引 push shift unshift 
      value.__proto__ = arrayMethods;
      // 如果数组里放的是对象我再监控
      this.observerArray(value);
    }else{
       // 对数组监控
      this.walk(value); // 对对象进行观测
    }
  }
  observerArray(value){ // [{}]
    for(let i = 0; i < value.length;i++){
      observe(value[i]);
    }
  }
  walk(data){
    let keys = Object.keys(data); // [name,age,address]
    // 如果这个data 不可配置 直接reurn
    keys.forEach((key)=>{
      defineReactive(data,key,data[key]);
    });
  }
}
function defineReactive(data,key,value){

  observe(value); // 递归实现深度检测
  Object.defineProperty(data,key,{
    configurable:true,
    enumerable:false,
    get(){ // 获取值的时候做一些操作
      return value;
    },
    set(newValue){ // 也可以做一些操作
      console.log('更新数据')
      if(newValue === value) return;
      observe(newValue); // 继续劫持用户设置的值,因为有可能用户设置的值是一个对象
      value = newValue;
    }
  });
}

export function observe(data) {
  let isObj = isObject(data);
  if (!isObj) {
    return
  }
  return new Observer(data); // 用来观测数据
}

重写原生数组方法

// 我要重写数组的那些方法 7个 push shift unshift pop reverse sort splice 会导致数组本身发生变化
// slice()


let oldArrayMethods = Array.prototype;
// value.__proto__ = arrayMethods 原型链查找的问题, 会向上查找,先查找我重写的,重写的没有会继续向上查找
// arrayMethods.__proto__ = oldArrayMethods
export const arrayMethods = Object.create(oldArrayMethods); 

const methods = [
  'push',
  'shift',
  'unshift',
  'pop',
  'sort',
  'splice',
  'reverse'
]
methods.forEach(method=>{
  arrayMethods[method] = function (...args) { 
    const result = oldArrayMethods[method].apply(this,args); // 调用原生的数组方法
    // push unshift 添加的元素可能还是一个对象
    let inserted; // 当前用户插入的元素
    let ob = this.__ob__;
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args;
        break;
      case 'splice': // 3个 新增的属性 splice 有删除 新增的的功能 arr.splice(0,1,{name:1})
        inserted = args.slice(2)
      default:
        break;
    }
    if(inserted) ob.observerArray(inserted); // 将新增属性继续观测


    return result;
  }
})

工具方法定义如下:

/**
 * 
 * @param {*} data 当前数据是不是对象
 */
export function isObject(data) {
  return typeof data === 'object' && data !== null;
}
export function def(data,key,value){
  Object.defineProperty(data,key,{
    enumerable:false,
    configurable:false,
    value
  })
}

到此这篇关于vue2.x数组劫持原理的实现的文章就介绍到这了,更多相关vue2.x 数组劫持内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于jquery的让textarea自适应高度的插件
Aug 03 Javascript
分享8款优秀的 jQuery 加载动画和进度条插件
Oct 24 Javascript
js sort 二维数组排序的用法小结
Jan 24 Javascript
javascript实现des解密加密全过程
Apr 03 Javascript
jquery中each遍历对象和数组示例
Aug 05 Javascript
设计模式中的组合模式在JavaScript程序构建中的使用
May 18 Javascript
三种带箭头提示框总结实例
Jun 14 Javascript
AngularJs Scope详解及示例代码
Sep 01 Javascript
jQuery使用EasyUi实现三级联动下拉框效果
Mar 08 Javascript
利用node.js本地搭建HTTP服务器
Apr 19 Javascript
angular框架实现全选与单选chekbox的自定义
Jul 06 Javascript
JS实现的全排列组合算法示例
Oct 09 Javascript
vue2.x 对象劫持的原理实现
Apr 19 #Javascript
基于js判断浏览器是否支持webGL
Apr 18 #Javascript
JavaScript对象字面量和构造函数原理与用法详解
Apr 18 #Javascript
javascript 内存模型实例详解
Apr 18 #Javascript
javascript-hashchange事件和历史状态管理实例分析
Apr 18 #Javascript
javascript使用Blob对象实现的下载文件操作示例
Apr 18 #Javascript
原生js实现的观察者和订阅者模式简单示例
Apr 18 #Javascript
You might like
建站常用13种PHP开源CMS比较
2009/08/23 PHP
php 5.4 全新的代码复用Trait详解
2017/01/05 PHP
[原创]php实现数组按拼音顺序排序的方法
2017/05/03 PHP
php双层循环(九九乘法表)
2017/10/23 PHP
javascript入门·图片对象(无刷新变换图片)\滚动图像
2007/10/01 Javascript
javascript禁用键盘功能键让右击及其他键无效
2013/10/09 Javascript
推荐8款jQuery轻量级树形Tree插件
2014/11/12 Javascript
javascript实现网页字符定位的方法
2015/07/14 Javascript
javascript电商网站抢购倒计时效果实现
2015/11/19 Javascript
javascript+css3 实现动态按钮菜单特效
2016/02/06 Javascript
JS小数运算出现多为小数问题的解决方法
2016/06/02 Javascript
BootStrap table表格插件自适应固定表头(超好用)
2016/08/24 Javascript
基于vue2.0动态组件及render详解
2018/03/17 Javascript
解决vue-router中的query动态传参问题
2018/03/20 Javascript
js canvas实现画图、滤镜效果
2018/11/27 Javascript
详解vue中v-model和v-bind绑定数据的异同
2020/08/10 Javascript
python使用Flask框架获取用户IP地址的方法
2015/03/21 Python
在Django的URLconf中使用多个视图前缀的方法
2015/07/18 Python
Python调用SQLPlus来操作和解析Oracle数据库的方法
2016/04/09 Python
详解Python函数作用域的LEGB顺序
2016/05/14 Python
Python内置模块logging用法实例分析
2018/02/12 Python
儿童编程python入门
2018/05/08 Python
用Python逐行分析文件方法
2019/01/28 Python
如何卸载python插件
2020/07/08 Python
Django web自定义通用权限控制实现方法
2020/11/24 Python
CSS实现半透明边框与多重边框的场景分析
2019/11/13 HTML / CSS
KEETSA环保床垫:更好的睡眠,更好的生活!
2016/11/24 全球购物
德国旅游网站:weg.de
2018/06/03 全球购物
英国莱斯特松木橡木家具网上商店:Choice Furniture Superstore
2019/07/05 全球购物
小班秋游活动方案
2014/02/22 职场文书
预备党员承诺书
2014/03/25 职场文书
应届生简历自我评价
2015/03/11 职场文书
爱心捐书倡议书
2015/04/27 职场文书
大学生饮品店创业计划书范文
2019/07/10 职场文书
使用Oracle跟踪文件的问题详解
2021/06/28 Oracle
windows11怎么查看wifi密码? win11查看wifi密码的技巧
2021/11/21 数码科技