浅谈vue实现数据监听的函数 Object.defineProperty


Posted in Javascript onJune 08, 2017

在 ES5中新增了不少新的API, 例如  新增了 Object.xxx相关的方法,其中有一个定义属性相关的 Object.defineProperty 这个方法(还有Object.defineProperties)这个方法是 vue框架实现数据监听的核心方法,它的定义如下:

Object.defineProperty([Object] obj, [String] propname, [Object] desp )

  1. @param  obj  要配置属性的某个对象
  2. @param propname 要配置的属性名,是一个字符串
  3. @param desp 对属性的描述,是一个对象,

desp 中可以配置的项目 

<1> writable:  true/false 是否可写

<2> configurable : true/false 是否可以配置,例如删除该属性

<3> enumerable: true/false 指的是是否可以使用 for in循环遍历属性

<4> value:  值  ,属性的值

我们在写vue项目的时候会在 data属性中添加我们自己的属性,这个属性在vue中是响应式的,也就是它可以监听到数据的变化,做出相应的改变(例如DOM操作)

我们自己利用 defineProperty给属性生成setter和getter(也就是其他编程语言里的存取器),就可以达到监听数据变化的目的

下面我们来自己实现一个数据监听的小 demo

有如下的数据

let vue = {
   data: {
    title: 'life style',
    content: 'bike walk sleep...'
   }
  };

已经提前声明的 data属性及其内部的属性,我们的目标是监听 data中,title和content的变化

如何做到呢? 属性的个数是不确定的,所以我们可以使用 for in循环遍历data对象的所有的属性

//如何监听用户自定义的 data中属性的改变?
  let data = vue.data;
  for (let prop in data) {
   data['__' + prop] = data[prop]; //存储私有属性
   Object.defineProperty(data, prop, {
    enumerable : true,
    set: function (newVal) {
     console.log('你正在修改'+prop + ' !...操作DOM...');
     // 数据校验
     this['__' + prop] = newVal;
    },
    get: function () {
     console.log('getter 获取值 ...');
     return this['__' + prop];
    }
   });
  }

遍历data属性的时候调用 defineProperty来给data对象的属性添加set和get方法,

我们给data添加一个新的属性   __xxx来保存我们之前的值,以便在 get方法中获取原来的值

set方法 用于监听这个属性被重新赋值,

get方法用于获取你想要的格式的值

此处需要注意的是 不要在 set和get中 使用this赋值或者取值,这样会导致循环调用,出现问题!!!

另外 我们不要使用 var,而要使用 let ,因为var不是块作用域, 会导致你最后访问到的prop总是最后一个

定义好之后,我们可以修改 data中title和content属性了,

当我们给 title赋值的时候回自动调用 set, 获取值得时候自动调用get

测试代码

// 赋值操作会调用这个属性的set方法, 类似于 set('aaa')
  data.title = 'aaa';
  // 获取值操作会调用这个属性的get方法
  console.log(data.title);
  data.content = 123;
  // 此种动态属性方式也会触发 set / get
  data['title'] = 123;
  console.log(data['title']);

结果(建议在最新版的chrome中操作):

浅谈vue实现数据监听的函数 Object.defineProperty

对刚刚的遍历方法还存在一些问题和说明:

1.data属性的某个属性可能还是对象,也就是存在多层级对象监听的问题

此时可以使用递归函数遍历data的属性,进行相同操作

2. 通过  data.title = 1是实际上是调用了 set方法, 这个类似于 OC中的点语法

3. 要同时定义多个属性,可以使用

Object.defineProperties([Object] obj, [Object] props);

需要注意的是, 本文只是介绍 defineProperty的基本使用,并非代表vue的代码实现

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript Event学习第十章 一些可替换的事件对
Feb 10 Javascript
关于JAVASCRIPT urldecode URL解码的问题
Jan 08 Javascript
jquery插件制作 手风琴Panel效果实现
Aug 17 Javascript
jquery选择器大全 全面详解jquery选择器
Mar 06 Javascript
JavaScript中定义函数的三种方法
Mar 12 Javascript
JS中prototype的用法实例分析
Mar 19 Javascript
JavaScript实现点击单元格改变背景色的方法
Feb 12 Javascript
修改ligerui 默认确认按钮的方法
Dec 27 Javascript
浅谈vuex为什么不建议在action中修改state
Feb 02 Javascript
详解为element-ui的Select和Cascader添加弹层底部操作按钮
Feb 07 Javascript
小程序卡片切换效果组件wxCardSwiper的实现
Feb 13 Javascript
js实现上传按钮并显示缩略图小轮子
May 04 Javascript
jQuery Validate表单验证插件实现代码
Jun 08 #jQuery
浅谈 Vue v-model指令的实现原理
Jun 08 #Javascript
Vue如何实现组件的源码解析
Jun 08 #Javascript
jquery Ajax实现Select动态添加数据
Jun 08 #jQuery
js canvas实现放大镜查看图片功能
Jun 08 #Javascript
vue实现一个移动端屏蔽滑动的遮罩层实例
Jun 08 #Javascript
微信小程序开发之map地图实现教程
Jun 08 #Javascript
You might like
使用 MySQL Date/Time 类型
2008/03/26 PHP
一贴学会PHP 新手入门教程
2009/08/03 PHP
PHP异步调用socket实现代码
2012/01/12 PHP
codeigniter框架批量插入数据
2014/01/09 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
学习ExtJS accordion布局
2009/10/08 Javascript
jquery的ajax从纯真网(cz88.net)获取IP地址对应地区名
2009/12/02 Javascript
flexigrid 参数说明
2010/11/23 Javascript
Javascript writable特性介绍
2015/02/27 Javascript
JavaScript中Object.prototype.toString方法的原理
2016/02/24 Javascript
手把手教你把nodejs部署到linux上跑出hello world
2017/06/19 NodeJs
vue之浏览器存储方法封装实例
2018/03/15 Javascript
详解Vue-cli webpack移动端自动化构建rem问题
2018/04/07 Javascript
nuxt.js 缓存实践
2018/06/25 Javascript
vue-cli3 取消eslint校验代码的解决办法
2020/01/16 Javascript
vue npm install 安装某个指定的版本操作
2020/08/11 Javascript
研究Python的ORM框架中的SQLAlchemy库的映射关系
2015/04/25 Python
使用python实现tcp自动重连
2017/07/02 Python
python实现趣味图片字符化
2019/04/30 Python
利用pyuic5将ui文件转换为py文件的方法
2019/06/19 Python
深入理解Python 多线程
2020/06/16 Python
自学python用什么系统好
2020/06/23 Python
Python使用socket模块实现简单tcp通信
2020/08/18 Python
python爬虫中url管理器去重操作实例
2020/11/30 Python
python爬虫scrapy基本使用超详细教程
2021/02/20 Python
帕克纽约:PARKER NY
2018/12/09 全球购物
数字漫画:comiXology
2020/06/13 全球购物
新党章心得体会
2014/09/04 职场文书
2015年元旦晚会活动总结(学生会)
2014/11/28 职场文书
初中英语教师个人工作总结2015
2015/07/21 职场文书
《失物招领》教学反思
2016/02/20 职场文书
opencv读取视频并保存图像的方法
2021/06/04 Python
Python实现打乒乓小游戏
2021/09/25 Python
angular异步验证器防抖实例详解
2022/03/31 Javascript
SQL Server中锁的用法
2022/05/20 SQL Server