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构造器的实现代码小结
May 16 Javascript
Js中的onblur和onfocus事件应用介绍
Aug 27 Javascript
javascript中HTMLDOM操作详解
Dec 11 Javascript
jQuery垂直多级导航菜单代码分享
Aug 18 Javascript
jQuery的promise与deferred对象在异步回调中的作用
May 03 Javascript
js阻止浏览器默认行为的简单实例
May 15 Javascript
JavaScript中对JSON对象的基本操作示例
May 21 Javascript
jQuery实现的小图列表,大图展示效果幻灯片示例
Oct 25 Javascript
在Vue.js中使用Mixins的方法
Sep 12 Javascript
AngularJS 监听变量变化的实现方法
Oct 09 Javascript
vue-cli 项目打包完成后运行文件路径报错问题
Jul 19 Javascript
Vue通过for循环随机生成不同的颜色或随机数的实例
Nov 09 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
采用ThinkPHP中F方法实现快速缓存实例
2014/06/13 PHP
PHP 无限级分类
2017/05/04 PHP
Nigma vs Alliance BO5 第三场2.14
2021/03/10 DOTA
javascript实现的距离现在多长时间后的一个格式化的日期
2009/10/29 Javascript
JavaScript学习笔记之数组的增、删、改、查
2016/03/23 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
2016/06/23 Javascript
JS文件上传神器bootstrap fileinput详解
2021/01/28 Javascript
javascript 正则表达式去空行方法
2017/01/24 Javascript
zTree获取当前节点的下一级子节点数实例
2017/09/05 Javascript
基于vue 动态加载图片src的解决方法
2018/02/05 Javascript
详解搭建es6+devServer简单开发环境
2018/09/25 Javascript
微信小程序实现Session功能及无法获取session问题的解决方法
2019/05/07 Javascript
Vue.js递归组件实现组织架构树和选人功能
2019/07/04 Javascript
jquery实现的分页显示功能示例
2019/08/23 jQuery
微信小程序定义和调用全局变量globalData的实现
2019/11/01 Javascript
微信小程序 scroll-view 实现锚点跳转功能
2019/12/12 Javascript
js实现批量删除功能
2020/08/27 Javascript
详解Vue.js 可拖放文本框组件的使用
2021/03/03 Vue.js
Python常用正则表达式符号浅析
2014/08/13 Python
python matplotlib绘图,修改坐标轴刻度为文字的实例
2018/05/25 Python
pandas.dataframe按行索引表达式选取方法
2018/10/30 Python
解决Python 命令行执行脚本时,提示导入的包找不到的问题
2019/01/19 Python
Python如何计算语句执行时间
2019/11/22 Python
Python scrapy增量爬取实例及实现过程解析
2019/12/24 Python
Android Q之气泡弹窗的实现示例
2020/06/23 Python
WWE美国职业摔角官方商店:WWE Shop
2018/11/15 全球购物
英国休闲奢华的缩影:Crew Clothing
2019/05/05 全球购物
周仰杰(JIMMY CHOO)法国官方网站:闻名世界的鞋子品牌
2019/09/27 全球购物
Ego Shoes官网:英国时髦鞋类品牌
2020/10/19 全球购物
如何保障Web服务器安全
2014/05/05 面试题
过滤器的用法
2013/10/08 面试题
本科生职业生涯规划书范文
2014/01/21 职场文书
护士上岗前培训自我鉴定
2014/04/20 职场文书
人事局接收函
2015/01/30 职场文书
教师求职简历自我评价
2015/03/10 职场文书
CSS中使用grid布局实现一套模板多种布局
2022/07/15 HTML / CSS