仿写Vue八、添加数组的方法

八、添加数组的方法

自己动手实践,就会更加深刻的理解**”**

这次处理数组的七个方法,使其成为响应式。

01、获取数组原型对象


重写每一个函数不现实,所以打算先获取数组的原型对象,然后生成一个新的对象来继承此原型对象,这个新的对象就拥有数组的一切属性方法,且不会对原生的数组产生任何影响。

/** 
* 对与响应式数组,我们需要重写其一些方法,例如 push、pop 
* 保证响应式数组使用这些方法之后依然是响应式的。 
*/
const arrProto = Array.prototype;
const arrMethods = Object.create(arrProto);

02、重写方法


我们需要覆盖七个方法:

const methodsToPatch = [  'push',  'pop',  'shift',  'unshift',  'sort',  'reverse',  'splice',]
    对于 **push, pop, splice**,响应式数组唯一不同的地方在于,对于往数组新加的数据项,需要保证其仍然是响应式的。其他的方法,要么是更改数据的位置,要么是删除某些数据,都不需要额外的处理,只需调用原来的方法即可。
function def(obj, key, val, enumerable) {
  Object.defineProperty(obj, key, {
    value: val,
    enumerable: !!enumerable,
    configurable: true,
    writable: true,
  })
}

methodsToPatch.forEach(method => {
  const original = arrMethods[method];
  def(arrMethods, method, function mutate() {
    console.log('调用的方法是:', method);
    
    let args = [], len = arguments.length;
    while (len--) args[len] = arguments[len];
    const result = original.apply(this, args);
    let inserted;
    const ob = this.__ob__;
    switch(method) {
      case 'push':
      case 'unshift':
        inserted = args; break;
      case 'splice':
        inserted = args.slice(2); break;
    }
    // 如果有新增的数据,则每个数据都将其响应式化
    if (inserted) {
      ob.observeArray(inserted);
    }
    return result;
  })
})

03、效果图


数据初始化:

    const data = {
      name: 'romeo',
      message: 'wants to be rich',
      deep: {
        firstLevel: {
          secondLevel: 'here!'
        }
      },
      arr: [
        { name: 'jack1' },
        { name: 'jack2' },
        { name: 'jack3' },
      ]
    }

在这里插入图片描述
可以看到 arr 中确实拥有了第四项,且同样是响应式的。

源代码在github上,请点击阅读原文查看~

在这里插入图片描述

Vue.js 2.x 中,为了实现响应式的数组,你可以使用下面的方法重写数组方法: 1. push:使用 `Array.prototype.push` 方法,然后手动调用 `Vue.set` 更新数组,例如: ```javascript this.array.push(newItem); Vue.set(this.array, this.array.length - 1, newItem); ``` 2. pop:使用 `Array.prototype.pop` 方法,然后手动调用 `Vue.delete` 删除最后一个元素,例如: ```javascript const deletedItem = this.array.pop(); Vue.delete(this.array, this.array.length); ``` 3. shift:使用 `Array.prototype.shift` 方法,然后手动调用 `Vue.delete` 删除第一个元素,例如: ```javascript const deletedItem = this.array.shift(); Vue.delete(this.array, 0); ``` 4. unshift:使用 `Array.prototype.unshift` 方法,在调用之前手动调用 `Vue.set` 更新数组的长度,例如: ```javascript this.array.unshift(newItem); Vue.set(this.array, 0, newItem); ``` 5. splice:使用 `Array.prototype.splice` 方法,然后手动调用 `Vue.delete` 删除或添加元素,例如: ```javascript // 删除元素 const deletedItems = this.array.splice(startIndex, deleteCount); for (let i = 0; i < deleteCount; i++) { Vue.delete(this.array, startIndex + i); } // 添加元素 this.array.splice(startIndex, 0, ...newItems); for (let i = 0; i < newItems.length; i++) { Vue.set(this.array, startIndex + i, newItems[i]); } ``` 通过手动调用 `Vue.set` 和 `Vue.delete`,你可以确保数组的变化能够触发 Vue.js 的响应式更新。 注意:以上方法适用于 Vue.js 2.x,在 Vue.js 3.x 中,你可以直接使用原生数组方法,因为 Vue.js 3.x 支持了 Proxy 来实现更好的响应式机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的桐人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值