Vue data的数据响应式到底是如何实现的


Posted in Javascript onFebruary 11, 2020

研究过程

一般形式

data:{ n:0 } :以这样的方式存储数据,vue能够监听其变化吗?显然是不能的。

使用Obj.defineProperty

let data1 = {}

Object.defineProperty(data1, 'n', {
value: 0  
})

为什么要使用defineProperty呢?这不是把一般形式复杂化了吗?

引出主角getter setter。

如果我们想对数据监听进行处理呢?(假设修改的数据必须>=0)

let data2 = {}
data2._n = 0

Object.defineProperty(data2,'n',{
  get(){ return this._n },
  set(value){
    if(value<0) return //在此处可以对数据的修改进行操作
    this._n = value
  }
})

使用代理

如果对方直接修改data2._n怎么办?我们让data2变成匿名对象!

let data3 = proxy({ data:{n:0} }) //括号里是匿名对象,无法访问
function proxy({data}){
 const obj = {}
 Object.defineProperty(obj, 'n', {
  get(){
    return data.n
  },
  set(value){
    if(value<0)return
    data.n = value
   }
 })
 return obj // obj 就是代理
}

代理是什么?

  • 对data的属性的读写,全权交给另一个对象obj负责,那么obj就是data的代理
  • data.n不使用,偏要使用obj.n来操作data.n

如果用户自己给匿名对象起了个名字怎么办呢?

MyData = { n:0 }
let data3 = proxy({ data:MyData })
MyData.n = -1
 //成功赋值为-1

这种情况,我们也要进行拦截处理。

//在4.中的proxy函数中加入这几行
let value = data.n
 Object.defineProperty(data, 'n', {
   get(){
     return value
   },
   set(newValue){
     if(newValue<0)return
     value = newValue
   }
 })

这样,我们就对data进行了监听。

data域的一个bug

new Vue({
  data:{
    obj:{
      a:0
    }
  },
  template:`
    <div @click="set">{{ obj.b }}</div>
  `,
  methods:{
    set(){
      this.obj.b = 1
    }
  }
})
  //bug:vue无法监听一开始data域中不存在的obj.b

解决方法:

data的初始化中加入b

data:{
  obj:{
    a:0,
    b:undefined 
    //注意,vue中的null和undefined都不会被渲染出来
  }
}

使用Vue.set(this.obj,'b',1)

数组的长度又不固定,怎么提前声明?

  1. 使用Vue.set (不推荐)
  2. 使用this.array.push (被Vue改写过的push,实现了代理和监听)

详见vue文档,变异方法 章节

总结

//看看下面的代码,发现了什么?

let data = proxy({ data:myData5 })
let vm = new Vue({ data: myData })

Vue正是使用了这种代理和监听的设计模式,形成的数据响应式。

流程:声明数据 => 监听数据 => 代理数据 => 返回数据

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

Javascript 相关文章推荐
document.getElementById的简写方式(获取id对象的简略写法)
Sep 10 Javascript
根据一段代码浅谈Javascript闭包
Dec 14 Javascript
JavaScript+html5 canvas制作的百花齐放效果完整实例
Jan 26 Javascript
jquery UI Datepicker时间控件冲突问题解决
Dec 16 Javascript
微信JS-SDK选取手机照片上传功能
Apr 21 Javascript
js绑定事件和解绑事件
Apr 27 Javascript
说说如何利用 Node.js 代理解决跨域问题
Apr 22 Javascript
js实现GIF动图分解成多帧图片上传
Oct 24 Javascript
在Vue项目中使用Typescript的实现
Dec 19 Javascript
ES6如何用一句代码实现函数的柯里化
Jan 18 Javascript
使用Typescript和ES模块发布Node模块的方法
May 25 Javascript
VUE解决跨域问题Access to XMLHttpRequest at
May 06 Vue.js
JS实现TITLE悬停长久显示效果完整示例
Feb 11 #Javascript
vue.config.js中配置Vue的路径别名的方法
Feb 11 #Javascript
vue-resourc发起异步请求的方法
Feb 11 #Javascript
js实现圆形显示鼠标单击位置
Feb 11 #Javascript
JavaScript实现省份城市的三级联动
Feb 11 #Javascript
node.js使用yargs处理命令行参数操作示例
Feb 11 #Javascript
node.js实现http服务器与浏览器之间的内容缓存操作示例
Feb 11 #Javascript
You might like
PHP中使用asort进行中文排序失效的问题处理
2014/08/18 PHP
php不使用copy()函数复制文件的方法
2015/03/13 PHP
你不知道的文件上传漏洞php代码分析
2016/09/29 PHP
php中Swoole的热更新实现代码实例
2021/03/04 PHP
JS图片无缝、平滑滚动代码
2014/03/11 Javascript
javascript数据类型示例分享
2015/01/19 Javascript
JQuery插入DOM节点的方法
2015/06/11 Javascript
jQuery获取选中单选按钮radio的值
2016/12/27 Javascript
JS简单获取并修改input文本框内容的方法示例
2018/04/08 Javascript
详解js中Array的方法及技巧
2018/09/12 Javascript
基于JS实现一个随机生成验证码功能
2019/05/29 Javascript
JQuery常用简单动画操作方法回顾与总结
2019/12/07 jQuery
vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)
2020/01/14 Javascript
Python获取linux主机ip的简单实现方法
2016/04/18 Python
在Python中Dataframe通过print输出多行时显示省略号的实例
2018/12/22 Python
对python调用RPC接口的实例详解
2019/01/03 Python
python监控进程状态,记录重启时间及进程号的实例
2019/07/15 Python
浅谈python3 构造函数和析构函数
2020/03/12 Python
Pandas替换及部分替换(replace)实现流程详解
2020/10/12 Python
Vision Directa智利眼镜网:框架眼镜、隐形眼镜和名牌太阳眼镜
2016/11/23 全球购物
MCAKE蛋糕官方网站:一直都是巴黎的味道
2018/02/06 全球购物
美国市场上最实惠的送餐服务:Dinnerly
2018/03/18 全球购物
英国折扣零售连锁店:QD Stores
2018/12/08 全球购物
时尚、社区、科技:SEVENSTORE
2019/04/26 全球购物
学生会主席就职演讲稿
2014/01/14 职场文书
运动会开幕式主持词
2014/03/28 职场文书
银行竞聘演讲稿范文
2014/04/23 职场文书
预防煤气中毒方案
2014/06/16 职场文书
工作感言一句话
2015/08/01 职场文书
Python基础之数据结构详解
2021/04/28 Python
GoLang中生成UUID唯一标识的实现
2021/05/08 Golang
nginx作grpc的反向代理踩坑总结
2021/07/07 Servers
python 远程执行命令的详细代码
2022/02/15 Python
宫崎骏十大动画电影,宫崎骏好看的动画电影排名
2022/03/22 日漫
postgreSQL数据库基础知识介绍
2022/04/12 PostgreSQL
Python实现双向链表基本操作
2022/05/25 Python