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 相关文章推荐
JavaScript学习笔记之Function对象
Jan 22 Javascript
EasyUI中combobox默认值注意事项
Mar 01 Javascript
解决jquery实现的radio重新选中的问题
Jul 03 Javascript
[原创]JQuery 在表单提交之前修改 提交的值
Apr 14 Javascript
浅谈JS运算符&amp;&amp;和|| 及其优先级
Aug 10 Javascript
Zabbix添加Node.js监控的方法
Oct 20 Javascript
jQuery实现的小图列表,大图展示效果幻灯片示例
Oct 25 Javascript
JavaScript 字符串数字左补位,右补位,取固定长度,截位扩展函数代码
Mar 25 Javascript
jquery将标签元素的高设为屏幕的百分比
Apr 19 jQuery
JS实现获取图片大小和预览的方法完整实例【兼容IE和其它浏览器】
Apr 24 Javascript
vue百度地图 + 定位的详解
May 13 Javascript
vue实现数字动态翻牌的效果(开箱即用)
Dec 08 Javascript
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
IP攻击升级,程序改进以对付新的攻击
2010/11/23 PHP
php通过记录IP来防止表单重复提交方法分析
2014/12/16 PHP
php使用curl伪造浏览器访问操作示例
2019/09/30 PHP
php+js实现的拖动滑块验证码验证表单操作示例【附源码下载】
2020/05/27 PHP
jQuery获得document和window对象宽度和高度的方法
2015/03/25 Javascript
JavaScript中使用Math.PI圆周率属性的方法
2015/06/14 Javascript
原生js模拟淘宝购物车项目实战
2015/11/18 Javascript
JS模拟简易滚动条效果代码(附demo源码)
2016/04/05 Javascript
在Html中使用Requirejs进行模块化开发实例详解
2016/04/15 Javascript
详解vue-cli 脚手架项目-package.json
2017/07/04 Javascript
如何以Angular的姿势打开Font-Awesome详解
2018/04/22 Javascript
Vue登录注册并保持登录状态的方法
2018/08/17 Javascript
vue使用better-scroll实现下拉刷新、上拉加载
2018/11/23 Javascript
vue 内置过滤器的使用总结(附加自定义过滤器)
2018/12/11 Javascript
详解React服务端渲染从入门到精通
2019/03/28 Javascript
微信小程序如何利用getCurrentPages进行页面传值
2019/07/01 Javascript
angularjs模态框的使用代码实例
2019/12/20 Javascript
js实现超级玛丽小游戏
2020/03/18 Javascript
vue相同路由跳转强制刷新该路由组件操作
2020/08/05 Javascript
举例讲解Python中的Null模式与桥接模式编程
2016/02/02 Python
Python使用正则表达式过滤或替换HTML标签的方法详解
2017/09/25 Python
keras 解决加载lstm+crf模型出错的问题
2020/06/10 Python
Python结合Window计划任务监测邮件的示例代码
2020/08/05 Python
python 爬取B站原视频的实例代码
2020/09/09 Python
pyqt5实现井字棋的示例代码
2020/12/07 Python
详解Python之Scrapy爬虫教程NBA球员数据存放到Mysql数据库
2021/01/24 Python
施华洛世奇美国官网:SWAROVSKI美国
2018/02/08 全球购物
Groupon西班牙官方网站:在线优惠券和交易,节省高达70%
2021/03/13 全球购物
100%羊绒:NakedCashmere
2020/08/26 全球购物
党的群众路线整改落实情况汇报
2014/10/28 职场文书
中国文明网2015年“向国旗敬礼”活动网上签名寄语
2015/09/24 职场文书
2016年秋季运动会通讯稿
2015/11/25 职场文书
利用ajax+php实现商品价格计算
2021/03/31 PHP
浅谈Redis位图(Bitmap)及Redis二进制中的问题
2021/07/15 Redis
Go 语言中 20 个占位符的整理
2021/10/16 Golang
Golang原生rpc(rpc服务端源码解读)
2022/04/07 Golang