前端Vue篇之Vue中封装的数组方法有哪些,如何实现页面更新

目录


Vue中封装的数组方法有哪些,如何实现页面更新

在 Vue 中,对于对象的响应式处理是通过 Object.defineProperty 来实现的,但是这种方式并不能直接监听到数组内部变化、长度变化以及截取操作等。为了让 Vue 能够监听到数组的这些变化,Vue 对数组进行了特殊处理。

数组的特殊处理

Vue 对数组的特殊处理主要包括两个方面:

  1. 重写数组的变异方法
    • Vue 重写了数组的变异方法(例如 push、pop、shift、unshift、splice、sort 和 reverse),在这些方法执行时,会触发通知机制,告知 Vue 数据发生了变化。
  2. 使用__proto__或者prototype
    • Vue 将数组的原型指向了一个特殊的对象,该对象包含了重写后的数组变异方法,这样就能够确保当调用这些方法时,能够触发数据更新。

Vue通过重写数组的变异方法,并且将数组的原型指向特殊对象的方式,使得 Vue 能够监听到数组的变化,从而确保了当数组发生变化时,页面能够及时地反映数据的变化。这种特殊处理让开发者在使用 Vue 时更加便利,不需要手动干预页面更新的过程,提供了更好的开发体验。

在Vue中,常用的数组方法封装在Vue实例的data属性中。这些方法包括:

  1. push()

    • 用法:this.array.push(newItem)
    • 功能:向数组末尾添加一个或多个元素
  2. pop()

    • 用法:this.array.pop()
    • 功能:删除并返回数组的最后一个元素
  3. shift()

    • 用法:this.array.shift()
    • 功能:删除并返回数组的第一个元素
  4. unshift()

    • 用法:this.array.unshift(newItem)
    • 功能:向数组的开头添加一个或多个元素,并返回新的长度
  5. splice()

    • 用法:this.array.splice(index, howMany, newItem1, ..., newItemX)
    • 功能:从数组中添加/删除项目,然后返回被删除的项目
  6. sort()

    • 用法:this.array.sort()
    • 功能:对数组元素进行排序
  7. reverse()

    • 用法:this.array.reverse()
    • 功能:颠倒数组中元素的顺序

实现页面更新

在Vue中,当使用上述数组方法修改数据时,Vue会自动检测到数据的变化,并触发相应的页面更新。

例如,当你使用 push 方法向数组中添加新元素时,Vue会自动更新相关的页面内容,无需手动干预页面更新的过程。这是因为Vue内部实现了响应式系统,它能够监听到数据的变化,并在数据改变时重新渲染相关的组件。

需要注意的是,在某些情况下,如果你直接使用索引更改数组元素,Vue可能无法自动检测到这种变化。在这种情况下,你可以使用 Vue.set 方法或者 array.splice 来确保 Vue 能够正确地追踪数组的变化并更新页面内容。

总之,Vue封装的数组方法能够简化数据操作,并且通过其内部的响应式系统,确保了当数组发生变化时,页面能够及时地反映数据的变化,从而提供了更好的开发体验。

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

javascript 复制代码
// 缓存数组原型
const arrayProto = Array.prototype
// 实现 arrayMethods.__proto__ === Array.prototype
export const arrayMethods = Object.create(arrayProto)
// 需要进行功能拓展的方法
const methodsToPatch = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']

/**
 * Intercept mutating methods and emit events
 */
methodsToPatch.forEach(function (method) {
  // 缓存原生数组方法
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator(...args) {
    // 执行并缓存原生数组功能
    const result = original.apply(this, args)
    // 响应式处理
    const ob = this.__ob__
    let inserted
    switch (method) {
      // push、unshift会新增索引,所以要手动observer
      case 'push':
      case 'unshift':
        inserted = args
        break
      // splice方法,如果传入了第三个参数,也会有索引加入,也要手动observer。
      case 'splice':
        inserted = args.slice(2)
        break
    }
    //
    if (inserted) ob.observeArray(inserted) // 获取插入的值,并设置响应式监听
    // notify change
    ob.dep.notify() // 通知依赖更新
    // 返回原生数组方法的执行结果
    return result
  })
})

这段代码是 Vue 中对数组方法进行拦截和响应式处理的关键部分。

  1. 缓存原生数组方法

    • 首先,代码通过 const arrayProto = Array.prototype 缓存了原生的数组方法,以备后续使用。
  2. 创建扩展后的数组对象

    • 然后,通过 Object.create(arrayProto) 创建了一个名为 arrayMethods 的对象,这样就可以在这个对象上添加新的方法或者重写原有的方法,而不影响原生的 Array.prototype
  3. 遍历需要拓展的方法

    • 接下来,代码遍历了需要拓展的数组方法,对每个方法进行拓展。这些方法包括 push、pop、shift、unshift、splice、sort 和 reverse。
  4. 拓展方法的实现

    • 对于每个方法,使用 def 函数将原生方法替换为新的方法。新方法在执行原生方法后,进行响应式处理并通知依赖更新。具体的响应式处理包括:
      • 获取操作的数据对象的 Observer 实例(ob)。
      • 根据操作类型,获取需要设置响应式监听的值。
      • 如果有需要设置响应式监听的值,调用 Observer 实例的 observeArray 方法进行处理。
      • 最后,通过 ob.dep.notify() 通知依赖更新。

需要注意的

  • 此段代码的作用是为 Vue 实现数组变更时的响应式更新。它会在数组的变更操作后,自动触发 Vue 的响应式更新机制,确保页面能够及时地反映数据的变化。
  • 在拓展数组方法时,需要考虑到新增的元素,确保新增的元素也能被设置为响应式数据。
  • 此段代码中的 def 函数可能是用来定义属性的,但在给出的代码中未提供该函数的实现。需要确保在代码其他地方有对该函数的定义和实现。

总结

以上代码片段主要实现了对数组方法的拦截和响应式处理,确保当数组发生变化时,Vue 能够自动更新相关的页面内容。这对于 Vue 来说是非常重要的,因为它保证了数据和视图之间的同步更新。

持续学习总结记录中,回顾一下上面的内容:
Vue中封装的数组方法包括push、pop、shift、unshift、splice、sort和reverse。页面更新是通过Vue对这些方法进行特殊处理,确保当数组发生变化时,Vue能够自动更新相关的页面内容。这样,开发者无需手动干预页面更新,提供了更好的开发体验。

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰9 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪9 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy10 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom11 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试