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 相关文章推荐
理清apply(),call()的区别和关系
Aug 14 Javascript
jquery小火箭返回顶部代码分享
Aug 19 Javascript
jQuery解决浏览器兼容性问题案例分析
Apr 15 Javascript
全面介绍javascript实用技巧及单竖杠
Jul 18 Javascript
jQuery时间日期三级联动(推荐)
Nov 27 Javascript
js实现九宫格的随机颜色跳转
Feb 19 Javascript
node中的cookie的具体使用
Sep 13 Javascript
bootstrap-table实现表头固定以及列固定的方法示例
Mar 07 Javascript
ES6 Map结构的应用实例分析
Jun 26 Javascript
亲自动手实现vue日历控件
Jun 26 Javascript
VUE渲染后端返回含有script标签的html字符串示例
Oct 28 Javascript
ES6 Iterator遍历器原理,应用场景及相关常用知识拓展详解
Feb 15 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
php中如何同时使用session和cookie来保存用户登录信息
2013/07/05 PHP
ThinkPHP3.1新特性之Action参数绑定
2014/06/19 PHP
ThinkPHP分页实例
2014/10/15 PHP
记录一次排查PHP脚本执行卡住的问题
2016/12/27 PHP
PHP登录(ajax提交数据和后台校验)实例分享
2016/12/29 PHP
PHP控制反转(IOC)和依赖注入(DI)
2017/03/13 PHP
关于Mozilla浏览器不支持innerText的解决办法
2011/01/01 Javascript
分享精心挑选的23款美轮美奂的jQuery 图片特效插件
2012/08/14 Javascript
基于jquery的文章中所有图片width大小批量设置方法
2013/08/01 Javascript
深入分析JSON编码格式提交表单数据
2015/06/25 Javascript
JavaScript中获取Radio被选中的值
2015/11/11 Javascript
js对字符串进行编码的方法总结(推荐)
2016/11/10 Javascript
jQuery实现图片滑动效果
2017/03/08 Javascript
Angular.js指令学习中一些重要属性的用法教程
2017/05/24 Javascript
JS匿名函数和匿名自执行函数概念与用法分析
2018/03/16 Javascript
vue移动端实现下拉刷新
2018/04/22 Javascript
karma+webpack搭建vue单元测试环境的方法示例
2018/05/24 Javascript
微信小程序引入VANT组件的方法步骤
2019/09/19 Javascript
vue跳转同一个组件,参数不同,页面接收值只接收一次的解决方法
2019/11/05 Javascript
VUE 组件转换为微信小程序组件的方法
2019/11/06 Javascript
JS实现放烟花效果
2020/03/10 Javascript
JS制作简易计算器的实例代码
2020/07/04 Javascript
python2.7读取文件夹下所有文件名称及内容的方法
2018/02/24 Python
Django中日期处理注意事项与自定义时间格式转换详解
2018/08/06 Python
Python基础之高级变量类型实例详解
2020/01/03 Python
用python批量下载apk
2020/12/29 Python
html5 Canvas画图教程(4)—未闭合的路径及渐变色的填充方法
2013/01/09 HTML / CSS
Meli Melo官网:名媛们钟爱的英国奢侈手包品牌
2017/04/17 全球购物
捷克鲜花配送:Florea.cz
2018/10/29 全球购物
医学生实习自我鉴定
2013/09/27 职场文书
小班秋游活动方案
2014/02/22 职场文书
三八红旗手先进事迹材料
2014/05/13 职场文书
企业总经理任命书
2014/06/05 职场文书
2014年副班长工作总结
2014/12/10 职场文书
2014年校长工作总结
2014/12/11 职场文书
企业计划生育责任书
2015/05/09 职场文书