Vue数据驱动模拟实现4


Posted in Javascript onJanuary 12, 2017

一、前言

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

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

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

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

下面,我们就一起来实现这些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.

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

Javascript 相关文章推荐
jQuery设置指定网页元素宽度和高度的方法
Mar 25 Javascript
基于MVC4+EasyUI的Web开发框架形成之旅之界面控件的使用
Dec 16 Javascript
基于React.js实现原生js拖拽效果引发的思考
Mar 30 Javascript
jquery中取消和绑定hover事件的实现代码
Jun 02 Javascript
用JS写的一个Ajax库(实例代码)
Aug 06 Javascript
jquery实现网站列表切换效果的2种方法
Aug 12 Javascript
jQuery插件FusionCharts绘制2D柱状图和折线图的组合图效果示例【附demo源码】
Apr 10 jQuery
vue2 前后端分离项目ajax跨域session问题解决方法
Apr 27 Javascript
ES6 如何改变JS内置行为的代理与反射
Feb 11 Javascript
vue写h5页面的方法总结
Feb 12 Javascript
vue中使用vee-validator完成表单校验方案
Nov 01 Javascript
javascript递归函数定义和用法示例分析
Jul 22 Javascript
移动端点击态处理的三种实现方式
Jan 12 #Javascript
js手机号批量滚动抽奖实现代码
Apr 17 #Javascript
js图片轮播手动切换特效
Jan 12 #Javascript
原生js实现倒计时功能(多种格式调用)
Jan 12 #Javascript
JavaScript定义全局对象的方法示例
Jan 12 #Javascript
Node.js制作简单聊天室
Jan 12 #Javascript
jQuery 插件实现随机自由弹跳气泡样式
Jan 12 #Javascript
You might like
VML绘图板②脚本--VMLgraph.js、XMLtool.js
2006/10/09 PHP
PHP容易被忽略而出错陷阱 数字与字符串比较
2011/11/10 PHP
destoon整合ucenter后注册页面不跳转的解决方法
2014/06/21 PHP
PHP+jQuery 注册模块的改进(一):验证码存入SESSION
2014/10/14 PHP
php计算两个文件相对路径的方法
2015/03/14 PHP
php限制ip地址范围的方法
2015/03/31 PHP
php中动态变量用法实例
2015/06/10 PHP
php 实现301重定向跳转实例代码
2016/07/18 PHP
php 使用html5实现多文件上传实例
2016/10/24 PHP
详解PHP文件的自动加载(autoloading)
2018/02/04 PHP
jQuery的实现原理的模拟代码 -1 核心部分
2010/08/01 Javascript
javascript的alert box在java中如何显示多行
2014/05/18 Javascript
Jquery-1.9.1源码分析系列(十一)之DOM操作
2015/11/25 Javascript
js实现获取两个日期之间所有日期的方法
2016/06/17 Javascript
easyui combotree加载静态数据问题(选不上)解决方法
2016/12/26 Javascript
vue2.0嵌套路由实现豆瓣电影分页功能(附demo)
2017/03/13 Javascript
深入解析js轮播插件核心代码的实现过程
2017/04/14 Javascript
解决Mac下安装nmp的淘宝镜像失败问题
2018/05/16 Javascript
element-ui 中的table的列隐藏问题解决
2018/08/24 Javascript
vue中$nextTick的用法讲解
2019/01/17 Javascript
Angular之jwt令牌身份验证的实现
2020/02/14 Javascript
javascript实现移动端触屏拖拽功能
2020/07/29 Javascript
使用vue引入maptalks地图及聚合效果的实现
2020/08/10 Javascript
使用python 爬虫抓站的一些技巧总结
2018/01/10 Python
Python实现的计算器功能示例
2018/04/26 Python
Pycharm 创建 Django admin 用户名和密码的实例
2018/05/30 Python
python多行字符串拼接使用小括号的方法
2020/03/19 Python
利用Python库Scapy解析pcap文件的方法
2019/07/23 Python
python序列化与数据持久化实例详解
2019/12/20 Python
python2 对excel表格操作完整示例
2020/02/23 Python
Python 线性回归分析以及评价指标详解
2020/04/02 Python
matplotlib 画双轴子图无法显示x轴的解决方法
2020/07/27 Python
零件设计自荐信范文
2013/11/27 职场文书
学生逃课检讨书
2015/02/17 职场文书
高校自主招生教师推荐信
2015/03/23 职场文书
绿里奇迹观后感
2015/06/15 职场文书