(Vue)Vue 中封装的数组方法有哪些,其如何实现页面更新(Vue源码解析)

Vue中封装的数组方法:

  1. push():

    • 描述:将一个或多个元素添加到数组的末尾。
    • 实现:通过拦截push方法,在添加元素后调用updateView方法来触发页面更新。
  2. pop():

    • 描述:移除数组的最后一个元素。
    • 实现:通过拦截pop方法,在移除元素后调用updateView方法来触发页面更新。
  3. shift():

    • 描述:移除数组的第一个元素。
    • 实现:通过拦截shift方法,在移除元素后调用updateView方法来触发页面更新。
  4. unshift():

    • 描述:将一个或多个元素添加到数组的开头。
    • 实现:通过拦截unshift方法,在添加元素后调用updateView方法来触发页面更新。
  5. splice():

    • 描述:从数组中添加或移除元素。
    • 实现:通过拦截splice方法,在添加或移除元素后调用updateView方法来触发页面更新。
  6. sort():

    • 描述:对数组元素进行排序。
    • 实现:通过拦截sort方法,在排序完成后调用updateView方法来触发页面更新。
  7. reverse():

    • 描述:颠倒数组中元素的顺序。
    • 实现:通过拦截reverse方法,在颠倒顺序后调用updateView方法来触发页面更新。

这些方法的实现都依赖于JavaScript的原型链和Object.defineProperty等技术,以便在调用这些方法时能够捕获到数据的变化,并及时更新页面。

总体而言,Vue通过劫持这些数组方法,实现了对数据的响应式处理,使得当数组发生变化时,相关的视图能够自动更新,提高了开发效率。

具体如何实现

在 Vue 中,对响应式处理利用的是 Object.defineProperty 对数据进行拦截,而这个方法并不能监听到数组内部变化,数组长度变化,数组的截取变化等,所以需要对这些操作进行 hack,让 Vue 能监听到其中的变化。

那 Vue 是如何实现让这些数组方法实现元素的实时更新的呢,下面是Vue 中对这些方法的封装:

js 复制代码
// src/core/observer/array.js


// 引入 def 函数,用于在对象上定义属性
import { def } from '../util/index';
// 获取数组的原型对象
const arrayProto = Array.prototype;
// 创建一个新的对象,该对象的原型是数组的原型对象,用于重写数组的方法
export const arrayMethods = Object.create(arrayProto);

// 通过遍历数组的一些方法,重写数组的方法
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) {
   // 获取原始的数组方法
  const original = arrayProto[method];

  // 在重写的数组方法上进行封装,使用 def 函数定义属性
  def(arrayMethods, method, function mutator (...args) {
    // 调用原始的数组方法,获取原始方法的返回值
    const result = original.apply(this, args);
    // 获取数组对象的 Observer 对象
    const ob = this.__ob__;

    // 对于一些方法(push、unshift、splice)可能会新增元素,需要进行响应式处理
    let inserted;
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args;
        break;
      case 'splice':
        // splice 方法的参数从第三个参数开始是新增的元素
        inserted = args.slice(2);
        break;
    }
    // 如果有新增的元素,调用 Observer 对象的 observeArray 方法进行观察
    if (inserted) ob.observeArray(inserted);

    // 通知变化
    ob.dep.notify();
    // 返回原始方法的返回值
    return result;
  });
});

上述代码首先创建了一个名为arrayMethods的对象,该对象继承自数组的原型对象Array.prototype。然后,通过循环遍历数组的一些方法(例如pushpopshift等),对这些方法进行了重新定义。在重新定义的方法中,先调用原始的数组方法,然后获取数组对象的__ob__属性,即其Observer对象。接着,根据不同的数组操作,可能会获取到新增的元素,然后调用observeArray方法对新增的元素进行观察,以实现嵌套对象的响应式处理。最后,通过ob.dep.notify()通知依赖该数组的Watcher进行更新。

简单来说就是,重写了数组中的那些原生方法,首先获取到这个数组的__ob__,也就是它的 Observer 对象,如果有新的值,就调用observeArray 继续对新的值观察变化(也就是通过 target__proto__ == arrayMethods 来改变了数组实例的型),然后手动调用 notify,通知渲染 watcher,执行 update。

相关推荐
狸克先生2 分钟前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
baiduopenmap16 分钟前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
loooseFish24 分钟前
小程序webview我爱死你了 小程序webview和H5通讯
前端
请叫我欧皇i36 分钟前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
533_39 分钟前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js
guokanglun1 小时前
空间数据存储格式GeoJSON
前端
陪学1 小时前
百度遭初创企业指控抄袭,维权还是碰瓷?
人工智能·百度·面试·职场和发展·产品运营
zhang-zan1 小时前
nodejs操作selenium-webdriver
前端·javascript·selenium
ZBY520311 小时前
【Vue】 npm install amap-js-api-loader指南
javascript·vue.js·npm
猫爪笔记1 小时前
前端:HTML (学习笔记)【2】
前端·笔记·学习·html