欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue数据驱动模拟实现4

程序员文章站 2022-12-28 16:50:22
一、前言 在"模拟vue之数据驱动3"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了。 当然,数组也是对象,也可以通过$...

一、前言

在"模拟vue之数据驱动3"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了。

当然,数组也是对象,也可以通过$set方法实现新增属性。

但是,对于数组而言,通常我们是通过push之类的方法吧。

ps:vue中明确指出push、pop、shift、unshift、splice、sort、reverse方法为变异方法,可以通过它们监听属性变化,触发视图更新(详情见)

下面,我们就一起来实现这些array的变异方法吧。

注:我们将array变异方法实现,也写在extendobj.js中的,因为数组也是对象嘛。

二、array变异方法实现

要实现这些变异方法,毫无疑问,我们会重写它们,那在array.prototype里面重写吗?

当然不是,这样不就影响了所有数组对象的原型链了么!

为了避免这种情况,且,我们只是想在监听数据对象上继承这些变异数组方法,那么细心的你会发现,其实与我们在"模拟vue之数据驱动3"中实现$set方法类似了。

首先,我们创建arrkeys对象用于保存需要变异的数组方法以及恒定对象extendarr,如下:

let arrkeys = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
const extendarr = [];

接着,就是在extendarr对象上,一一监听arrkeys中的方法了,与$set方法类似,整体结构如下:

!function(){
  arrkeys.foreach(function(key){
    proxyobject(extendarr, key, function(){
      //todo
    });
  });
}();

注:proxyobject方法其实核心就是object.defineproperty,详见"模拟vue之数据驱动3".

接下来,就是实现核心部分代码了,重写这些方法的目的,是为了监听数据变化,所以要在方法原有功能不变的情况下,重写它们,array.xxx.apply即可实现原有功能。

且,push、unshift、splice这三个方法可以在原数组中,新增属性,故而,我们需要监听新增属性以及它们的属性值,这里就和$set方法完全一样了,通过$observer,即可利用observe以及convert方法实现了。

实现代码如下:

!function(){
  arrkeys.foreach(function(key){
    proxyobject(extendarr, key, function(){
      console.log('fun ' + key + ' is observed');
      let result;
      let arrproto = array.prototype;
      let ob = this.$observer;
      let arr = arrproto.slice.call(arguments);
      let inserted;
      let index;
      switch(key){
        case 'push': {
          inserted = arr;
          index = this.length;
          break;
        }
        case 'unshift': {
          inserted = arr;
          index = 0;
          break;
        }
        case 'splice': {
          inserted = arr.slice(2);
          index = arr[0];
          break;
        }
      }
      result = arrproto[key].apply(this, arguments);
      if(inserted){
        inserted.foreach(val => {
          ob.observe(val);
          ob.convert(index++, val);
        });
      }
      return result;
    });
  });
}();

最后,就是在需要监听的对象上继承这些变异方法咯,如下:

//observer.js
function observer(data){
  if(!(this instanceof observer)){
    return new observer(data);
  }
  data.__proto__ = extendobj;
  //继承变异方法push、pop等等
  if(array.isarray(data)){
    data.__proto__.__proto__ = extendarr;
  }
  this.data = data;
  this.walk(data);  
}

好了,一切完毕,接下来就测试下呗:

<script src="./extendobj.js"></script>
<script src="./observer.js"></script>
<script>
  'use strict';
  let data = {
    msg: [5, 2, 0],
    user: {
      name: 'monkey',
      age: 24
    },
    lover: {
      name: 'dorie',
      age: 23
    }
  };
  observer(data);
</script>

效果如下:

Vue数据驱动模拟实现4

perfect,此时,你可能会想,数组方法中仅有push、unshift、splice会为数组新增属性,那么我们又何必将其他方法,例如sort、reverse重写呢,也没发现有什么猫腻呢?

不错,在此时,并没有什么卵用,但是,你要知道sort、reverse等这些方法,可是会引起数组变化的,那么就会影响视图展现,这些变化,又怎么通知数组呢?就是下篇随笔会具体说明的。

该篇随笔代码,详情见github.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。