浅谈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 相关文章推荐
JQuery 应用 JQuery.groupTable.js
Dec 15 Javascript
jQuery写的日历(包括日历的样式及功能)
Apr 23 Javascript
jquery实现网页查找功能示例分享
Feb 12 Javascript
JS清除选择内容的方法
Jan 29 Javascript
jQuery代码实现发展历程时间轴特效
Jul 30 Javascript
jQuery中$.ajax()和$.getJson()同步处理详解
Aug 12 Javascript
浅析JavaScript中浏览器的兼容问题
Apr 19 Javascript
利用yarn实现一个webpack+react种子
Oct 25 Javascript
Javascript中this关键字指向问题的测试与详解
Aug 11 Javascript
vue-router启用history模式下的开发及非根目录部署方法
Dec 23 Javascript
详解vue 自定义marquee无缝滚动组件
Apr 09 Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
Jul 28 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 SPL标准库之文件操作(SplFileInfo和SplFileObject)实例
2015/05/11 PHP
php返回当前日期或者指定日期是周几
2015/05/21 PHP
PHP中的一些常用函数收集
2015/05/26 PHP
PHP实现简单汉字验证码
2015/07/28 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
2015/12/10 PHP
PHP+MySql+jQuery实现的&quot;顶&quot;和&quot;踩&quot;投票功能
2016/05/21 PHP
CI(CodeIgniter)框架实现图片上传的方法
2017/03/24 PHP
php file_get_contents取文件中数组元素的方法
2017/04/01 PHP
PHP使用pdo实现事务处理操作示例
2018/09/05 PHP
原型方法的不同写法居然会影响调试的解决方法
2007/03/08 Javascript
jquery load()在firefox(火狐)下显示不正常的解决方法
2011/04/05 Javascript
ff下JQuery无法监听input的keyup事件的解决方法
2013/12/12 Javascript
提交按钮的name='submit'引起的js失效问题及原因
2015/02/25 Javascript
JavaScript使用pop方法移除数组最后一个元素用法实例
2015/04/06 Javascript
CSS3实现动态背景登录框的代码
2015/07/28 Javascript
jquery实现未经美化的简洁TAB菜单效果
2015/08/28 Javascript
CSS或者JS实现鼠标悬停显示另一元素
2016/01/22 Javascript
AngularJS 过滤器的简单实例
2016/07/27 Javascript
微信小程序 wxapp内容组件 text详细介绍
2016/10/31 Javascript
jquery 标签 隔若干行加空白或者加虚线的方法
2016/12/07 Javascript
Vue实现双向绑定的方法
2016/12/22 Javascript
Vue组件模板形式实现对象数组数据循环为树形结构(实例代码)
2017/07/31 Javascript
vue中beforeRouteLeave实现页面回退不刷新的示例代码
2019/11/01 Javascript
原生JS与CSS实现软件卸载对话框功能
2019/12/05 Javascript
JS实现长图上下滚动效果
2020/03/19 Javascript
Python实现冒泡排序的简单应用示例
2017/12/11 Python
Django如何自定义分页
2018/09/25 Python
生产管理的三大手法
2013/11/11 职场文书
关于赌博的检讨书
2014/01/24 职场文书
关于美容院的活动方案
2014/08/14 职场文书
教师批评与自我批评发言稿
2014/10/15 职场文书
法定代表人资格证明书
2015/06/18 职场文书
大学校园餐饮创业计划书
2019/08/07 职场文书
中国古代史学名著《战国策》概述
2019/08/09 职场文书
nginx七层负载均衡配置详解
2022/07/15 Servers
Python爬取奶茶店数据分析哪家最好喝以及性价比
2022/09/23 Python