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 相关文章推荐
ajax 缓存 问题 requestheader
Aug 01 Javascript
IE事件对象(The Internet Explorer Event Object)
Jun 27 Javascript
JS自动适应的图片弹窗实例
Jun 29 Javascript
JS关键字球状旋转效果的实例代码
Nov 29 Javascript
JS实现可自定义大小,可双击关闭的弹出层效果
Oct 16 Javascript
js+css简单实现网页换肤效果
Dec 29 Javascript
javascript正则表达式总结
Feb 29 Javascript
基于jquery实现智能表单验证操作
May 09 Javascript
浅谈Node异步编程的机制
Oct 18 Javascript
vue中实现滚动加载更多的示例
Nov 08 Javascript
微信小程序使用自定义组件导航实现当前页面高亮
Jan 02 Javascript
Node.js+Vue脚手架环境搭建的方法步骤
Mar 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
在MongoDB中模拟Auto Increment的php代码
2011/03/06 PHP
PHP通过iconv将字符串从GBK转换为UTF8字符集
2011/07/18 PHP
采集邮箱的php代码(抓取网页中的邮箱地址)
2012/07/17 PHP
PHP实现通用alert函数的方法
2015/03/11 PHP
php处理json格式数据经典案例总结
2016/05/19 PHP
Yii 2.0实现联表查询加搜索分页的方法示例
2017/08/02 PHP
利用cookie记住背景颜色示例代码
2013/11/04 Javascript
js实现正方形颜色从下往上升的效果
2014/08/04 Javascript
javascript中错误使用var造成undefined
2016/03/31 Javascript
js 上传文件预览的简单实例
2016/08/16 Javascript
JS实现随机颜色的3种方法与颜色格式的转化
2017/01/05 Javascript
nodejs个人博客开发第二步 入口文件
2017/04/12 NodeJs
vue input 输入校验字母数字组合且长度小于30的实现代码
2018/05/16 Javascript
js全屏事件fullscreenchange 实现全屏、退出全屏操作
2019/09/17 Javascript
JavaScript多种滤镜算法实现代码实例
2019/12/10 Javascript
JavaScript实现移动端带transition动画的轮播效果
2020/03/24 Javascript
element中Steps步骤条和Tabs标签页关联的解决
2020/12/08 Javascript
Python 多进程并发操作中进程池Pool的实例
2017/11/01 Python
利用selenium 3.7和python3添加cookie模拟登陆的实现
2017/11/20 Python
PyTorch快速搭建神经网络及其保存提取方法详解
2018/04/28 Python
python的concat等多种用法详解
2018/11/28 Python
pandas每次多Sheet写入文件的方法
2018/12/10 Python
Pycharm以root权限运行脚本的方法
2019/01/19 Python
python基于socket进行端口转发实现后门隐藏的示例
2019/07/25 Python
python数据持久存储 pickle模块的基本使用方法解析
2019/08/30 Python
Python打印特殊符号及对应编码解析
2020/05/07 Python
python获取系统内存占用信息的实例方法
2020/07/17 Python
Python eval函数原理及用法解析
2020/11/14 Python
.NET程序员的几道面试题
2012/06/01 面试题
鞋类设计与工艺专业销售求职信
2013/11/01 职场文书
成绩单家长评语大全
2014/04/16 职场文书
开工仪式策划方案
2014/05/23 职场文书
事业单位考察材料范文
2014/12/25 职场文书
大学生志愿者心得体会
2016/01/15 职场文书
发工资啦!教你用Python实现邮箱自动群发工资条
2021/05/10 Python
让JavaScript代码更加精简的方法技巧
2022/06/01 Javascript