浅谈Vue响应式(数组变异方法)
很多初使用Vue的同学会发现,在改变数组的值的时候,值确实是改变了,但是视图却无动于衷,果然是因为数组太高冷了吗?
查看官方文档才发现,不是女神太高冷,而是你没用对方法。
看来想让女神自己动,关键得用对方法。虽然在官方文档中已经给出了方法,但是在下实在好奇的紧,想要解锁更多姿势的话,那就必须先要深入女神的心,于是乎才有了去探索Vue响应式原理的想法。(如果你愿意一层一层地剥开我的心。你会发现,你会讶异…… 沉迷于鬼哭狼嚎 无法自拔QAQ)。
前排提示,Vue的响应式原理主要是使用了ES5的Object.defineProperty,毫不知情的同学可以查看相关资料。
为啥数组不响应?
仔细一想,Vue的响应是基于Object.definePropery的,这个方法主要是对对象属性的描述进行修改。数组其实也是对象,通过定义数组的属性应该也能产生响应的效果呀。先验证一下自己的想法,撸起袖子就开干。
const arr = [1,2,3];
let val = arr[0];
Object.defineProperty(arr,'0',{
enumerable: true,
configurable: true,
get(){
doSomething();
return val;
},
set(a){
val = a;
doSomething();
}
});
function doSomething() {
}
然后在控制台中分别输入arr、arr[0] = 2、arr,可以看到如下图的结果。
咦,一切居然都如预想猜想的一样。
接下来,看到这段代码,有的同学可能会有所疑问,为啥在get()方法里不直接返回this[0]呢?而是要借助val来返回值呢?仔细一想,卧槽!!!差点特么的死循环了,你想呀,get()本身就是获取当前属性的值,在get()里调用this[0]不是等同于再次调用了get()方法吗? 好可怕好可怕,简直吓死劳资了。
虽然你想象中的女神可能会这种姿势,但是你眼前的这个女神确实不是这种姿势的,像我这种屌丝属性暴露无疑的人怎么可能猜透女神的心思?为什么不这样响应数据呢?或许是因为数组和对象还是有所差别,定义数组的属性可能会产生一些麻烦与Bug。又或许是因为在交互的过程中可能会产生大量的数据,导致整体的性能下降。也有可能是作者权衡利弊之后用其他方法也可以达到数据响应的效果。反正我是猜不透啦。
为啥调用数组原生方法就可以响应了?
为什么使用了这些数组的方法就就能让数据响应了呢?先看看数组部分的源码吧。
简单的来讲,def的作用就是重新定义对象属性的value值。
//array.js
import { def } from '../util/index'
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
//arrayMethods是对数组的原型对象的拷贝,
//在之后会将该对象里的特定方法进行变异后替换正常的数组原型对象
/**
* Intercept mutating methods and emit events
*/[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
.forEach(function (method) {
// cache original method
//将上面的方法保存到original中
const original = arrayProto[method]
def(arrayMethods, method, function mutator (...args) {
const result = original.apply(this, args)const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
// notify change
ob.dep.notify()
return result
})
})
贴出def部分的代码
/**
* Define a property.
*/
export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
})
}
array.js是对数组的一些方法进行变异,我们以push方法来举个例子。首先 就是要用original = arrayProto['push']来保存原生的push方法。
然后就是要定义变异的方法了,对于def函数,如果不深究的话,def(arrayMethods,method,function(){}),这个函数可以粗略的表示为arrayMethods[method] = function mutator(){};
假设在之后调用push方法,实际上调用的是mutator方法,在mutator方法中,第一件事就是调用保存了原生push方法的original,先求出实际的值。一堆文字看起来实在很抽象,那么写一段低配版的代码来表达源码的含义。
const push = Array.prototype.push;
Array.prototype.push = function mutator (...arg){
const result = push.apply(this,arg);
doSomething();
return result
}
function doSomething(){
console.log('do something');
}
const arr = [];
arr.push(1);
arr.push(2);
arr.push(3);
在控制台中查看结果为:。
那么源码中的
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
// notify change
ob.dep.notify()
这段代码就是对应的doSomething()了
在该代码中,清清楚楚的写了2个单词的注释notify change,不认识这2个单词的同学就百度一下嘛,这里就由我代劳了,这俩单词的意思是发布改变!每次调用了该方法,都会求出值,然后做一些其他的事情,比如发布改变与观察新增的元素,响应的其他过程在本篇就不讨论了。
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
目前一共有这么些方法,只要用对方法就能改变女神的姿势哟!
小结
对于标题,我一改再改,一开始叫浅析Vue响应原理,但是后来一看 这个标题实在太大,那就从最简单的入手吧,先从数组入手,而且本篇也不会花费太多时间去阅读。如果本篇有什么地方写得有误,误导了他人,请一定指出,万分感激。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
- Vue实现双向绑定的原理以及响应式数据的方法
- 基于Vue2x实现响应式自适应轮播组件插件VueSliderShow功能
- 浅谈Vue 数据响应式原理
- 浅谈实现vue2.0响应式的基本思路
- Vue的事件响应式进度条组件实例详解
- 代码详解Vuejs响应式原理
- Vue响应式原理深入解析及注意事项
- Vue如何实现响应式系统
文章同步发布: https://www.geek-share.com/detail/2736655998.html
浅谈Vue响应式(数组变异方法)的更多相关文章
- 浅谈vue响应式原理及发布订阅模式和观察者模式
一.Vue响应式原理 首先要了解几个概念: 数据响应式:数据模型仅仅是普通的Javascript对象,而我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率. 双向绑定:数据改变,视图 ...
- 浅谈html5 响应式布局
一.什么是响应式布局? 响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本. 这个概念是为解决移动互联 ...
- 浅谈6种JS数组遍历方法的区别
本篇文章给大家介绍一下6种JS数组遍历方法:for.foreach.for in.for of.. each. ().each的区别.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. ...
- 【浅谈html5 响应式布局之自动适应屏幕宽度】
允许网页宽度自动调整 “自适应网页设计”到底是怎么做到的?其实并不难. 首先,在网页代码的头部,加入一行viewport元标签. <meta name=”viewport” content=”w ...
- 浅谈Vue中计算属性(computed)和方法(methods)的差别
浅谈Vue中计算属性(computed)和方法(methods)的差别 源码地址 methods方法和computed计算属性,两种方式的最终结果确实是完全相同 计算属性是基于它们的响应式依赖进行缓存 ...
- vue数组变异方法
Vue数组变异方法,会改变被这些方法调用的原始数组,将会触发视图更新 push() 接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度 pop() 从数组末尾移除最后一项,减少数组的 ...
- Vue响应式原理及总结
Vue 的响应式原理是核心是通过 ES5 的保护对象的 Object.defindeProperty 中的访问器属性中的 get 和 set 方法,data 中声明的属性都被添加了访问器属性,当读取 ...
- 深度解析 Vue 响应式原理
深度解析 Vue 响应式原理 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还是进 ...
- Vue源码--解读vue响应式原理
原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...
随机推荐
- Effective C++(9) 构造函数调用virtual函数会发生什么
问题聚焦: 不要在构造函数和析构函数中调用virtual函数,因为这样的调用不会带来你预想的结果. 让我先来看一下在构造函数里调用一个virtual函数会发生什么结果 Demo class Trans ...
- Java学习---JBPM[工作流]学习
点击参考 更多参考 链接:https://pan.baidu.com/s/1A1AH5sXu7yhV3mncpH4Z6w 密码:88zw
- December 11th 2016 Week 51st Sunday
If a thing is worth doing it is worth doing well. 如果事情值得做,那就做好. If it is worth doing, then it is wor ...
- 只用最适合的! 全面对比主流 .NET 报表控件:水晶报表、FastReport、ActiveReports 和 Stimulsoft
前言 随着 .NET 平台的出现,报表相关的开发控件随之出现,目前已经有若干成熟的产品可供开发人员使用,本文旨在通过从不同维度对比目前最流行的4款 .NET报表控件,给所有报表开发人员在做产品选型时一 ...
- HDFS Namenode&Datanode
HDFS Namenode&Datanode HDFS 机制粗略示意图 客户端写入文件流程: NN && DN Namenode(NN)工作机制 NN是整个文件系统的管理节点. ...
- 理解活在Iphone中的那些App (四)
App生存环境之宿主环境 终于开始说一些技术性的话题了,从这里开始的一些技术细节的东西,以前我也没有太刻意的注意过.为了写这个也是刚刚看了一点资料,如果有纰漏,恳请指出. 一个App生存的宿主环境主要 ...
- vue-cli + webpack自动生成项目
# 全局安装 vue-cli $ npm install --global vue-cli # 创建一个基于 webpack 模板的新项目 $ vue init webpack palanWebsit ...
- webstorm中导入git项目
1.打开webStrom 配置git File–setting
- 该网页已屏蔽以下插件Adobe Flash Player
2017.6.9更新:多谢网友留言,该网页已屏蔽以下插件Adobe Flash Player解决方法:chrome://flags/#run-all-flash-in-allow-mode选择启用就O ...
- oracle数据库之用户管理
转载 Oracle创建用户.角色.授权.建表 一.oracle数据库的权限系统分为系统权限与对象权限: 系统权限( database system privilege )可以让用户执行特定的命令集 ...