vue2源码学习(二)---监听数组的变化

2022/7/4 1:21:35

本文主要是介绍vue2源码学习(二)---监听数组的变化,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在监听对象变化的基础上只修改了observe.js,新增了array.js

通过重写数组内的会改变数组本身的方法进行监听数组的变化

//observe.js
import { newArrayProto } from './array'

class Observer {
  constructor (data) {
    console.log(data,this)
    //  Object.defineProperty只能劫持已经存在的属性(所以vue里定义了$set,$delete)

    Object.defineProperty(data,'__ob__',{
      value:this,
      enumerable:false//将__ob__变为不可枚举(循环的时候无法获取,避免死循环)
    })
    // data.__ob__ = this
    //判断是否是数组
    if (Array.isArray(data)) {
      //  重写数组部分方法(保留数组原有的特性)
      data._proto_ = newArrayProto
      this.observeArray(data)
    } else {
      this.walk(data)
    }
  }

  walk (data) {
    //重新定义属性
    Object.keys(data).forEach(key => defineReactive(data, key, data[key]))
  }

  observeArray (data) {
    data.forEach(item => observe(item))
  }
}

export function defineReactive (target, key, value) {//闭包
  observe(value) //对所有的对象进行属性劫持
  Object.defineProperty(target, key, {
    get () {//取值的时候会执行get
      return value
    },
    set (newV) {//修改的时候会执行set
      if (newV === value) return
      observe(newV)//防止新值为对象,所以对新值进行再次代理
      value = newV
    },
  })
}

export function observe (data) {
//  对data进行劫持
  if (typeof data !== 'object' || data == null) {
    return;//只对对象进行劫持
  }
  if(data.__ob__ instanceof Observer){
    return
  }
//  如果一个对象被劫持过了,就不需要再劫持了(判断一个对象是否被接吃过,可以增添一个实例,用实例来判断)

  return new Observer(data)
}
//array.js重写数组中的部分方法
let oldArrayProto = Array.prototype

export let newArrayProto = Object.create(oldArrayProto)

//所有能修改原数组的方法
let methods = [
  'push',//向数组的末尾添加一个或更多元素,并返回新的长度。
  'pop',//删除数组的最后一个元素并返回删除的元素。
  'shift',//    删除并返回数组的第一个元素。
  'unshift',//向数组的开头添加一个或更多元素,并返回新的长度。
  'reverse',//反转数组的元素顺序。
  'sort',//对数组进行排序(可以穿进去一个函数)
  'splice',//splice(n,m)删除数组的第n个到第m-1个(不包含m个)从数组中添加或删除元素。
]

methods.forEach(method => {
  newArrayProto[method] = function (...args) {//重写数组方法
    const result = oldArrayProto[method].call(this, ...args)//内部调用原来的方法,函数的劫持,切片编程
    //需要对新增的数据再次进行劫持
    let ob = this.__ob__
    let inserted;
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
      default:
        break
    }
    console.log(inserted) //新增的内容
    if (inserted) {
      //  对新增的内容再次进行劫持
      ob.observeArray(inserted)

    }

    return result
  }
})

 



这篇关于vue2源码学习(二)---监听数组的变化的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程