浅谈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 相关文章推荐
40款非常棒的jQuery 插件和制作教程(系列一)
Oct 26 Javascript
JS弹出窗口代码大全(详细整理)
Dec 21 Javascript
Ext GridPanel加载完数据后进行操作示例代码
Jun 17 Javascript
将页面table内容与样式另存成excel文件的方法
Aug 05 Javascript
js实现选中复选框文字变色的方法
Aug 14 Javascript
JS简单实现多级Select联动菜单效果代码
Sep 06 Javascript
jQuery zTree加载树形菜单功能
Feb 25 Javascript
详解JavaScript正则表达式之分组匹配及反向引用
Mar 09 Javascript
Winform客户端向web地址传参接收参数的方法
May 17 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
Oct 26 Javascript
vue.js2.0点击获取自己的属性和jquery方法
Feb 23 jQuery
微信小程序swiper实现文字纵向轮播提示效果
Jan 21 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
PHP实用函数分享之去除多余的0
2015/02/06 PHP
PHP实现打包下载文件的方法示例
2017/10/07 PHP
jquery 常用操作方法
2010/01/28 Javascript
JQuery从头学起第二讲
2010/07/04 Javascript
javascript之Partial Application学习
2013/01/10 Javascript
JS获取地址栏参数的小例子
2013/08/23 Javascript
javascript制作的滑动图片菜单
2015/05/15 Javascript
JS基于面向对象实现的拖拽库实例
2015/09/24 Javascript
JS弹出窗口插件zDialog简单用法示例
2016/06/12 Javascript
JSON字符串和对象相互转换实例分析
2016/06/16 Javascript
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
AngularJS实现tab选项卡的方法详解
2017/07/05 Javascript
Vue数组更新及过滤排序功能
2017/08/10 Javascript
基于Vue实现后台系统权限控制的示例代码
2017/08/29 Javascript
使用vs code开发Nodejs程序的使用方法
2017/09/21 NodeJs
vue.js实现只弹一次弹框
2018/01/29 Javascript
Layui Form 自定义验证的实例代码
2019/09/14 Javascript
jQuery 图片查看器插件 Viewer.js用法简单示例
2020/04/04 jQuery
jQuery cookie的公共方法封装和使用示例
2020/06/01 jQuery
[01:10:49]Secret vs VGJ.S 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
Python网络编程 Python套接字编程
2017/09/13 Python
Python程序运行原理图文解析
2018/02/10 Python
python实现人民币大写转换
2018/06/20 Python
Python数据集切分实例
2018/12/08 Python
Python实现名片管理系统
2020/02/14 Python
x-ua-compatible content=”IE=7, IE=9″意思理解
2013/07/22 HTML / CSS
详解HTML5中的拖放事件(Drag 和 drop)
2016/11/14 HTML / CSS
详解canvas绘制网络字体几种方法
2019/08/27 HTML / CSS
阿迪达斯俄罗斯官方商城:adidas俄罗斯
2017/03/08 全球购物
翻译学院毕业生自荐书
2014/02/02 职场文书
实习会计求职自荐信范文
2014/03/10 职场文书
环保标语大全
2014/06/12 职场文书
教师群众路线学习心得体会
2014/11/04 职场文书
企业爱心捐款倡议书
2015/04/27 职场文书
捐款仪式主持词
2015/07/04 职场文书
CentOS8.4安装Redis6.2.6的详细过程
2021/11/20 Redis