关于vue中如何监听数组变化


Posted in Vue.js onApril 28, 2021

前言

前段时间学习了关于vue中响应式数据的原理,(并作了学习笔记vue响应式原理),其实是通过Object.defineProperty控制getter和setter,并利用观察者模式完成的响应式设计。那么数组有一系列的操作方法,这些方法并不会触发数组的getter和setter方法。那么vue中针对数组的响应式设计是如何实现的呢...那么我们一起去学习下吧~

源码部分

https://github.com/vuejs/vue/blob/dev/src/core/observer/array.js

从哪开始第一步学习呢

Emmmm...
我觉得要先把Vue中的数据响应式原理弄清楚,这样对于理解vue中是如何检测数组的变化才比较好,所以,可以去网上找下文章然后配合源码进行阅读,相信你一定会理解的。推荐下我之前看的一篇博客,还有我看过后自己写的学习记录吧,哈哈。

vue响应式原理

vue的双向绑定原理和实现

好的,先看看这个吧。哈哈!

从图开始

咱们先看下下面的图,先了解下vue中实现的思路,这样接下来再看源码的实现,会一清二楚,明明白白。

关于vue中如何监听数组变化

看到这个图然后思考一下,是不是大致了解了~

首先判断浏览器是否支持__proto__指针

重写数组的这7个方法,然后根据是否支持__proto__,将改写后的数组指向数组的prototype。

是不是很简单!!!

看看源码吧

了解了实现原理,那么我们再看看源码吧,看下源码主要是更深入的了解作者是如何实现的,也可以看下优秀的代码编码方式,加以学习。

关于一些解释我就写在下面的代码块中了哈!

//https://github.com/vuejs/vue/blob/dev/src/core/observer/array.js


//def方法是基于Object.defineProperty封装的一层方法,很简单,我会在下面把代码贴出来,免得大家去找了。
import { def } from '../util/index' 

//保存下原生的数组原型对象
const arrayProto = Array.prototype

//进行原型连接,将arrayMethods的原型指向Array.prototype
export const arrayMethods = Object.create(arrayProto)

const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]

methodsToPatch.forEach(function (method) {
  // 缓存原生的方法
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator (...args) {
    var args = [], 
    len = arguments.length;
    while (len--) args[len] = arguments[len];
    const result = original.apply(this, args) // 原来的数组方法执行结果
    const ob = this.__ob__ // 这个__ob__就是Observe的实例~~~~
    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted) // 如果数组有变化,则重新调用observeArray
    // notify change
    ob.dep.notify()  //
    return result
  })
})

这个是关于Observe的代码:

var Observer = function Observer(value) {
    this.value = value;
    this.dep = new Dep();
    this.vmCount = 0;
    def(value, '__ob__', this);  //这里会看到在每个对象数据上都会绑定一个Observe的实例,所以上面代码中的this.__ob__就是这个
    if (Array.isArray(value)) { // 这里判断是否是数组类型的数据,如果是的话就走observeArray
      if (hasProto) {
        protoAugment(value, arrayMethods);
      } else {
        copyAugment(value, arrayMethods, arrayKeys);
      }
      this.observeArray(value); //这里就是处理数组类型的数据,如下
    } else {
      this.walk(value);
    }
  };

如下是observeArray的实现:

Observer.prototype.observeArray = function observeArray(items) {
    for (var i = 0, l = items.length; i < l; i++) {
      observe(items[i]); // 这个observe方法如下
    }
  };

在这里我们看下observe这个方法:

function observe(value, asRootData) {
    if (!isObject(value) || value instanceof VNode) {
      return
    }
    var ob;
    if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
      ob = value.__ob__;
    } else if (
      shouldObserve &&
      !isServerRendering() &&
      (Array.isArray(value) || isPlainObject(value)) &&
      Object.isExtensible(value) &&
      !value._isVue
    ) {
      ob = new Observer(value);
    }
    if (asRootData && ob) {
      ob.vmCount++;
    }
    return ob
  }

这个是关于def方法的实现,很简单我就不说了哈:

function def (obj, key, val, enumerable) {
    Object.defineProperty(obj, key, {
      value: val,
      enumerable: !!enumerable,
      writable: true,
      configurable: true
    });
}

以上就是关于vue中如何监听数组变化的详细内容,更多关于vue如何监听数组的资料请关注三水点靠木其它相关文章!

Vue.js 相关文章推荐
vue中音频wavesurfer.js的使用方法
Feb 20 Vue.js
vue实现表格合并功能
Dec 01 Vue.js
vue3.0+vue-router+element-plus初实践
Dec 02 Vue.js
Vue——解决报错 Computed property &quot;****&quot; was assigned to but it has no setter.
Dec 19 Vue.js
vue-quill-editor插入图片路径太长问题解决方法
Jan 08 Vue.js
Vue+Bootstrap实现简易学生管理系统
Feb 09 Vue.js
如何在 Vue 中使用 JSX
Feb 14 Vue.js
vue实现简单数据双向绑定
Apr 28 Vue.js
vue+elementui 实现新增和修改共用一个弹框的完整代码
Jun 08 Vue.js
关于Vue中的options选项
Mar 22 Vue.js
vue中this.$http.post()跨域和请求参数丢失的解决
Apr 08 Vue.js
Vue深入理解插槽slot的使用
Aug 05 Vue.js
vue实现简单数据双向绑定
Apr 28 #Vue.js
vue引入Excel表格插件的方法
Apr 28 #Vue.js
原生JS封装vue Tab切换效果
vue项目两种方式实现竖向表格的思路分析
vue首次渲染全过程
浅谈vue2的$refs在vue3组合式API中的替代方法
Vue.js 带下拉选项的输入框(Textbox with Dropdown)组件
You might like
探讨:如何编写PHP扩展
2013/06/13 PHP
老版本PHP转义Json里的特殊字符的函数
2015/06/08 PHP
php过滤输入操作之htmlentities与htmlspecialchars用法分析
2017/02/17 PHP
php post json参数的传递和接收处理方法
2018/05/31 PHP
JavaScript 动态将数字金额转化为中文大写金额
2009/05/14 Javascript
一个可以兼容IE FF的加为首页与加入收藏实现代码
2009/11/02 Javascript
jquery 跳到顶部和底部动画2句代码简单实现
2013/07/18 Javascript
jquery实现点击文字可编辑并修改保存至数据库
2014/04/15 Javascript
浅谈Sizzle的“编译原理”
2015/04/14 Javascript
jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点
2015/12/01 Javascript
javaScript事件学习小结(四)event的公共成员(属性和方法)
2016/06/09 Javascript
jquery easyui validatebox remote的使用详解
2016/11/09 Javascript
10个在JavaScript开发中常遇到的BUG
2017/12/18 Javascript
jquery应用实例分享_实现手风琴特效
2018/02/01 jQuery
React Native开发封装Toast与加载Loading组件示例
2018/09/08 Javascript
微信小程序的tab选项卡的实现效果
2019/05/15 Javascript
Vue强制组件重新渲染的方法讨论
2020/02/03 Javascript
[56:00]DOTA2上海特级锦标赛主赛事日 - 4 胜者组决赛Secret VS Liquid第一局
2016/03/05 DOTA
Python 面向对象 成员的访问约束
2008/12/23 Python
Python中的并发编程实例
2014/07/07 Python
python排序方法实例分析
2015/04/30 Python
Python复制文件操作实例详解
2015/11/10 Python
Python爬取京东的商品分类与链接
2016/08/26 Python
Python 使用requests模块发送GET和POST请求的实现代码
2016/09/21 Python
python虚拟环境virtualenv的安装与使用
2017/09/21 Python
Python实现进程同步和通信的方法
2018/01/02 Python
Linux下python制作名片示例
2018/07/20 Python
浅谈python 中的 type(), dtype(), astype()的区别
2020/04/09 Python
Python存储读取HDF5文件代码解析
2020/11/25 Python
一文带你了解Python 四种常见基础爬虫方法介绍
2020/12/04 Python
倩碧香港官方网站:Clinique香港
2017/11/13 全球购物
什么是执行力?9个故事告诉您:成功绝非偶然!
2019/07/05 职场文书
使用 CSS 轻松实现一些高频出现的奇形怪状按钮
2021/12/06 HTML / CSS
PC版《死亡搁浅导剪版》现已发售 展开全新的探险
2022/04/03 其他游戏
用PYTHON去计算88键钢琴的琴键频率和音高
2022/04/10 Python
Python 视频画质增强
2022/04/28 Python