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 相关文章推荐
jQuery 阴影插件代码分享
Jan 09 Javascript
js正则表达exec与match的区别说明
Jan 29 Javascript
JS比较2个日期间隔的示例代码
Apr 15 Javascript
Google 地图事件实例讲解
Aug 06 Javascript
微信小程序 教程之WXML
Oct 18 Javascript
jQuery实现大图轮播
Feb 13 Javascript
100行代码理解和分析vue2.0响应式架构
Mar 09 Javascript
JS简单实现父子窗口传值功能示例【未使用iframe框架】
Sep 20 Javascript
js replace替换字符串同时替换多个方法
Nov 27 Javascript
小程序实现搜索界面 小程序实现推荐搜索列表效果
May 18 Javascript
jQuery zTree插件快速实现目录树
Aug 16 jQuery
使用vue3重构拼图游戏的实现示例
Jan 25 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
如何实现给定日期的若干天以后的日期
2006/10/09 PHP
PHP 金额数字转换成英文
2010/05/06 PHP
PHP strip_tags保留多个HTML标签的方法
2016/05/22 PHP
PDO::beginTransaction讲解
2019/01/27 PHP
Yii框架函数简单用法分析
2019/09/09 PHP
Google Map API更新实现用户自定义标注坐标
2009/07/29 Javascript
ExtJs GridPanel简单的增删改实现代码
2010/08/26 Javascript
asm.js使用示例代码
2013/11/28 Javascript
用jQuery模拟select下拉框的简单示例代码
2014/01/26 Javascript
jQuery on()方法绑定动态元素的点击事件无响应的解决办法
2016/07/07 Javascript
js仿小米官网图片轮播特效
2016/09/29 Javascript
JavaScript 详解预编译原理
2017/01/22 Javascript
使用gulp搭建本地服务器并实现模拟ajax
2017/04/05 Javascript
js实现关闭网页出现是否离开提示
2017/12/07 Javascript
node中modules.exports与exports导出的区别
2018/06/08 Javascript
angularjs 动态从后台获取下拉框的值方法
2018/08/13 Javascript
用python实现的去除win下文本文件头部BOM的代码
2013/02/10 Python
在Python中移动目录结构的方法
2016/01/31 Python
基于anaconda下强大的conda命令介绍
2018/06/11 Python
详解爬虫被封的问题
2019/04/23 Python
Python tkinter实现图片标注功能(完整代码)
2019/12/08 Python
Pyorch之numpy与torch之间相互转换方式
2019/12/31 Python
CSS3实现类似翻书效果的过渡动画的示例代码
2019/09/06 HTML / CSS
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
2018/01/03 HTML / CSS
世界上最大的罕见唱片、CD和音乐纪念品网上商店:991.com
2018/05/03 全球购物
德国珠宝和手表在线商店:VALMANO
2019/03/24 全球购物
团工委书记自荐书范文
2013/12/17 职场文书
车间副主任岗位职责
2013/12/24 职场文书
2014全国两会学习心得体会1000字
2014/03/10 职场文书
勤俭节约倡议书
2014/04/14 职场文书
学生安全承诺书
2014/05/22 职场文书
电子信息工程自荐信
2014/05/26 职场文书
我的兄弟姐妹观后感
2015/06/15 职场文书
2015年国培研修感言
2015/08/01 职场文书
Python自动化测试PO模型封装过程详解
2021/06/22 Python
Three.js实现雪糕地球的使用示例详解
2022/07/07 Javascript