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 相关文章推荐
JavaScript常用全局属性与方法记录积累
Jul 03 Javascript
javascript仿php的print_r函数输出json数据
Sep 13 Javascript
javascript自然分类法算法实现代码
Oct 11 Javascript
在每个匹配元素的外部插入新元素的方法
Dec 20 Javascript
js+jquery实现图片裁剪功能
Jan 02 Javascript
js使用Array.prototype.sort()对数组对象排序的方法
Jan 28 Javascript
浅谈JavaScript for循环 闭包
Jun 22 Javascript
jQuery操作dom实现弹出页面遮罩层(web端和移动端阻止遮罩层的滑动)
Aug 25 Javascript
js addDqmForPP给标签内属性值加上双引号的函数
Dec 24 Javascript
js实现拖拽功能
Mar 01 Javascript
vue项目引入Iconfont图标库的教程图解
Oct 24 Javascript
JavaScript DOM常用操作代码汇总
Jul 03 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
PHP自毁程序(慎用)
2015/07/09 PHP
PHP查询并删除数据库多列重复数据的方法(利用数组函数实现)
2016/02/23 PHP
鼠标滑在标题上显示图片的JS代码
2013/11/19 Javascript
jQuery Validate 验证,校验规则写在控件中的具体实例
2014/02/27 Javascript
jquery中常用的函数和属性详细解析
2014/03/07 Javascript
使用JavaScript的ActiveXObject对象检测应用程序是否安装的方法
2014/04/15 Javascript
Javascript中数组sort和reverse用法分析
2014/12/30 Javascript
浅谈NodeJS中require路径问题
2015/05/07 NodeJs
基于JavaScript代码实现随机漂浮图片广告
2016/01/05 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
2016/09/04 Javascript
vue获取DOM元素并设置属性的两种实现方法
2017/09/30 Javascript
快速搭建vue2.0+boostrap项目的方法
2018/04/09 Javascript
详解Angularjs 自定义指令中的数据绑定
2018/07/19 Javascript
vue权限路由实现的方法示例总结
2018/07/29 Javascript
实例详解vue.js浅度监听和深度监听及watch用法
2018/08/16 Javascript
4个顶级JavaScript高级文本编辑器
2018/10/10 Javascript
JavaScript ECMA-262-3 深入解析(一):执行上下文实例分析
2020/04/25 Javascript
[01:45]2014DOTA2 TI预选赛预选赛 大神专访第二弹!
2014/05/20 DOTA
django rest framework之请求与响应(详解)
2017/11/06 Python
python3使用pandas获取股票数据的方法
2018/12/22 Python
Python类的继承用法示例
2019/01/31 Python
np.newaxis 实现为 numpy.ndarray(多维数组)增加一个轴
2019/11/30 Python
tensorflow之并行读入数据详解
2020/02/05 Python
Python基于smtplib模块发送邮件代码实例
2020/05/29 Python
Html5之title吸顶功能
2018/06/04 HTML / CSS
递归计算如下递归函数的值(斐波拉契)
2012/02/04 面试题
学生会竞选自荐信
2013/10/12 职场文书
周年庆典主持词
2014/04/02 职场文书
企业演讲稿范文大全
2014/05/20 职场文书
电气工程及其自动化专业毕业生自荐信
2014/06/21 职场文书
群众路线个人剖析材料
2014/10/07 职场文书
小班上学期幼儿评语
2014/12/30 职场文书
奖金申请报告模板
2015/05/15 职场文书
房贷工资证明范本
2015/06/12 职场文书
学生会自荐信
2019/05/16 职场文书
python实现学生信息管理系统(面向对象)
2022/06/05 Python