源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Vue数据驱动模拟实现4

  • 时间:2020-08-31 14:03 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Vue数据驱动模拟实现4
[b]一、前言[/b] 在"[url=http://www.1sucai.cn/article/102651.htm]模拟Vue之数据驱动3[/url]"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了。 当然,数组也是对象,也可以通过$set方法实现新增属性。 但是,对于数组而言,通常我们是通过push之类的方法吧。 PS:Vue中明确指出push、pop、shift、unshift、splice、sort、reverse方法为变异方法,可以通过它们监听属性变化,触发视图更新(详情见[url=http://cn.vuejs.org/v2/guide/list.html#%E5%8F%98%E5%BC%82%E6%96%B9%E6%B3%95]here[/url]) 下面,我们就一起来实现这些Array的变异方法吧。 注:我们将Array变异方法实现,也写在extendObj.js中的,因为数组也是对象嘛。 [b]二、Array变异方法实现 [/b] 要实现这些变异方法,毫无疑问,我们会重写它们,那在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
    });
  });
}();
[b]注:[/b]proxyObject方法其实核心就是Object.defineProperty,详见"[url=http://www.1sucai.cn/article/102651.htm]模拟Vue之数据驱动3[/url]". 接下来,就是实现核心部分代码了,重写这些方法的目的,是为了监听数据变化,所以要在方法原有功能不变的情况下,重写它们,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>
效果如下: [img]http://files.jb51.net/file_images/article/201701/2017112140230421.gif?201701214240[/img] Perfect,此时,你可能会想,数组方法中仅有push、unshift、splice会为数组新增属性,那么我们又何必将其他方法,例如sort、reverse重写呢,也没发现有什么猫腻呢? 不错,在此时,并没有什么卵用,但是,你要知道sort、reverse等这些方法,可是会引起数组变化的,那么就会影响视图展现,这些变化,又怎么通知数组呢?就是下篇随笔会具体说明的。 该篇随笔代码,详情见[url=https://github.com/jajk/imitativeVue/tree/master/Observer/version3]github[/url]. 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程素材网。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部