(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。

相关推荐
juruiyuan1111 小时前
FFmpeg3.4 libavcodec协议框架增加新的decode协议
前端
Peter 谭2 小时前
React Hooks 实现原理深度解析:从基础到源码级理解
前端·javascript·react.js·前端框架·ecmascript
LuckyLay3 小时前
React百日学习计划——Deepseek版
前端·学习·react.js
gxn_mmf3 小时前
典籍知识问答重新生成和消息修改Bug修改
前端·bug
hj10433 小时前
【fastadmin开发实战】在前端页面中使用bootstraptable以及表格中实现文件上传
前端
乌夷4 小时前
axios结合AbortController取消文件上传
开发语言·前端·javascript
晓晓莺歌4 小时前
图片的require问题
前端
码农黛兮_464 小时前
CSS3 基础知识、原理及与CSS的区别
前端·css·css3
水银嘻嘻5 小时前
web 自动化之 Unittest 四大组件
运维·前端·自动化
(((φ(◎ロ◎;)φ)))牵丝戏安5 小时前
根据输入的数据渲染柱形图
前端·css·css3·js