IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue源码系列之 响应式数据处理2 数组的重写 -> 正文阅读

[JavaScript知识库]vue源码系列之 响应式数据处理2 数组的重写

目录

vue源码系列之 响应式数据处理2 数组的重写

vue源码系列之 响应式数据处理1 链接: link.

array.js

  • 对数组的方法进行重写
    • oldArrayPrototype 原始的数组方法
    • arrayMethos = Object.create(oldArrayPrototype) 创建一个新的对象,也就是拷贝原始数组的方法
    • methods 中的方法,是会影响原始数组的,因此需要重写这些方法
    • 遍历这些会改原始数组的方法,然后执行步骤是
      • 先执行自己定义的arrayMethos 方法,之后再调用原始数组的方法
      • 其中最主要的是:假如args传入的实参为 对象时候 则需要特殊处理
      • inserted 为新增要插入的数据( [ [1,2,3] , {name:“ppp”} ] )类似这种需要特殊处理
      • 然后假设有新增数据时,则需要继续劫持,观测数组里面的每一项数据
let oldArrayPrototype = Array.prototype; // 原始的数组方法
export let arrayMethos = Object.create(oldArrayPrototype); // 数组方法的重写
// 其中arrayMethos_proto_ = Array.prototype
let methods = [
  'push',
  'shift',
  'unshift',
  'pop',
  'reverse',
  'sort',
  'splice'
]
methods.forEach(method => {
  // 用户调用了以上几个方法 会用自己重写的,否者使用原来的数组方法
  arrayMethos[method] = function (...args) { // 先调用自己写的方法,之后调用内部原有的方法
    // console.log("改变了原始数组"); // arr.push(1,2) -> [1,2]
    oldArrayPrototype[method].call(this, ...args);
    // 假如args传入的实参为 对象时候 则需要特殊处理
    let inserted;
    let ob = this.__ob__; // 根据当前数组实例获取到observer实例对象
    switch (method) {
      case "push":
      case "unshift":
        args; // 就是新增的内容
      case "splice":
        args.slice(2)
      default:
        break;
    }
    // 如果有新增的内容 要进行继续劫持, 我需要观测的数组里的每一项,而不是数组
    if (inserted) ob.observeArray(inserted);
    // 如果数组中的数据是对象类型,需要监控对象的变化
  }
})

observe / index.js

  • 作用:观察者监听数据的变化,实现数据的响应式
  • 执行流程:
  • Observer观察者之内首先判断是对象还是数组
    • 是对象的时候,则是执行 walk() 方法,对对象属性的劫持,转化为响应式属性
      • 其中转化为响应式属性是采用 Object.defineProperty方法
      • 值得注意的是:若是设置新值时,为对象,则需要继续监听
      • 因此对于 data.__ob__属性,则需要设置为不可枚举,否者会陷入死循环
    • 为数组的时候:
      • 拿到重写的方法,赋值给当前对象的属性,也就是重写的方法
      • 值得注意的是:数组内含有数组或者对象时候,又需要针对数组进行监听 this.observeArray(data);
      • observeArray(data)遍历数组中的每一项,然后进行观测 observe(item)
    • 引入 数组重写的方法 arrayMethos
import {
  arrayMethos
} from "../array";
import {
  isObject
} from "../utils";
// 检测数据的变化 类是有类型的,对象是无类型!
class Observer {
  constructor(data) { // 对对象中的所有属性 进行劫持
    Object.defineProperty(data, '__ob__', {
      value: "this",
      enumerable: false, //不可枚举 之后也就无法遍历到 walk()
    })
    if (Array.isArray(data)) { // 数组劫持 -> 对数组的原来方法进行改写,切片编程,高阶函数
      data.__proto__ = arrayMethos;
      // 如果数组中的数据是对象类型,需要监控对象的变化
      this.observeArray(data);
    } else {
      this.walk(data); // 对每一个对象劫持后 调用一次
    }
  }
  // 遍历数组
  observeArray(data) { // 针对数组中的数组 和 数组中的对象再一次劫持 递归了
    data.forEach(item => {
      observe(item)
    })
  }
  // 遍历对象
  walk(data) {
    Object.keys(data).forEach(key => {
      defineReactive(data, key, data[key]); // 把对象中的属性 定义为响应式数据
    })
  }
}
// vue2 对对象进行遍历后 将每个属性 用defineProperty重新定义 -> 造成性能较差
function defineReactive(data, key, value) {
  // 注意点:就是value为对象的时候,需要再劫持
  observe(value); // 本身默认传入的数据为对象套对象时,则需要递归劫持
  // console.log("defineReactive", data, key, value); // defineReactive {name: 'xpl'} name xpl
  Object.defineProperty(data, key, {
    get() { // 取值
      return value;
    },
    set(newVal) { // 设置data新的值
      observe(newVal) // 对数据进行修改时 是一个对象,又需要劫持,修改为响应式数据
      value = newVal;
    }
  })
}

// 观察者 监听data数据
export function observe(data) {
  // console.log("observe内的", data); // observe内的 {name: 'xpl'}
  // 如果为对象的时候 才观测
  if (!isObject(data)) {
    return;
  }
  if (data.__ob__) { // 如果数组已经被劫持了观测过了
    return;
  }
  // 默认而言 data是一个对象
  return new Observer(data)
}
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章           查看所有文章
加:2021-11-09 19:23:29  更:2021-11-09 19:26:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:41:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码