vue.js的双向数据绑定Object.defineProperty方法的神奇之处


Posted in Javascript onJanuary 18, 2019

vue.js 2.0版的双向数据绑定就是通过Object.defineProperty方法实现的,俗称属性拦截器。

这么说吧,vue.js是通过它实现双向绑定的。俗称属性拦截器。而且专门用来监控对象属性变化的Object.observe方法也被草案发起人撤回了(此方法在node环境中仍能使用)。可见defineProperty的威力之大。

Object.defineProperty()    不支持ie8

方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。

// 语法: 
/*
 * Object.defineProperty(obj,prop,descriptor)
 * @param: obj:需要定义属性的对象;
 *     prop:需要定义或修改的属性;
 *     descriptor:将被定义或修改属性的描述符{}
 * 返回值 : 返回传入函数的对象,即第一个参数obj
 */

对象里目前存在的属性描述符主要有两种形式: 数据描述符和存取描述符.

数据描述符: 拥有可写或不可写值的属性*

        可选键值:
        configurable: 当且仅当configurable为true时,改属性描述符才能够被改变,也能被删除
        enumerable: 当其值为true时,该属性才能够出现在对象的枚举属性中,默认为false
        writable: 当且仅当该属性的值为true时,该属性才能被赋值运算符改变, 默认为false。
        value: 该属性对应的值,可以是任意有效的javascript的值(数值,对象,函数等),默认为undefined

存取描述符: 由一对getter-setter函数功能来描述的属性*

        可选键值:
        configurable: 当且仅当configurable为true时,改属性描述符才能够被改变,也能被删除
        enumerable: 当其值为true时,该属性才能够出现在对象的枚举属性中,默认为false
        get: 给属性提供getter的方法,如果没有 getter 则为undefined。当我们读取某个属性的时候,其实是在对象内部调用了该 方法,此方法必须要有return语句。该方法返回值被用作属性值。默认为 undefined
        set:设置属性值的方法, 如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。也就是说,当我们设置某个属性的时候,实际上是在对象的内部调用了该方法

note:两者不能同时定义, 否则报错==

get和set是我们今天要重点讨论的两个方法,先看一下他们的简单实例:

实例:

var a = {}; 
Object.defineProperty(a, 'b', { 
  set: function(newValue) { 
    console.log('赋值操作, 赋值' + newValue); 
  }, 
  get: function() { 
    console.log('取值操作'); 
    return 2; //这里需注意 我硬让他返回2
  } 
}); 
a.b = 1; // 赋值操作,赋值1 
a.b; // 取值操作2

虽然我将a.b的值设置成了1,但是因为我在get方法中始终返回了2,所以a.b的值一直是2。

那么,这就好玩儿了:我们可以在页面监听某个变量,当变量发生变化的时候,我们就更新对应的视图。由数据来驱动视图的更新,是不是很熟悉?是的,vue .js的核心思想就是这个。我们写个小例子:

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8" />
  <title>defineProperty</title>
 </head>
 <body>
  <div id="test">这是一个测试</div>
  <script>
   var view = document.getElementById("test");
   var data = {};
   var i = 0;
   Object.defineProperty(data, "b", {
    set: function(newValue) {
     //当data.b的值改变的时候更新#test的视图
     view.textContent = newValue;
    },
    get: function() {}
   });
   setInterval(function() {
    i++;
    data["b"] = "data.b的值更新了,我要更新视图" + i;
   }, 2000);
  </script>
 </body>
</html>

视图的变化过程:

vue.js的双向数据绑定Object.defineProperty方法的神奇之处

最开始的视图:

vue.js的双向数据绑定Object.defineProperty方法的神奇之处

2秒后的视图:

vue.js的双向数据绑定Object.defineProperty方法的神奇之处

重点理解:

// 3.Object.defineProperty(obj,propertyName,{}):给对象添加属性(指定描述符)
  const obj = {
    firstName: 'A',
    lastName: 'B',
  }
  // 给obj添加fullName属性
  // obj.fullName = 'A-B'
  /*
    1.数据描述符
      configurable: 是否可以重新定义
      enumerable: 是否可以枚举
      value: 初始值
      writable: 是否可以修改属性值
    2.访问描述符
      get: 回调函数,根据其它相关的属性动态计算得到当前属性值
      set: 回调函数,监视当前属性值的变化,更新其它相关的属性值
  */
  Object.defineProperty(obj,'fullName',{
    get() {
      return this.firstName+'-'+this.lastName;
    },
    set(value) {
      const names = value.split('-');
      this.firstName = names[0];
      this.lastName = names[1];
    }
  })
  console.log(obj.fullName);//A-B
  obj.firstName = 'C';
  obj.lastName = 'D';
  console.log(obj.fullName);//C-D
  obj.fullName = 'E-F';
  console.log(obj.firstName,obj.lastName);//E F

Object对象有一个freeze的方法,用于实现对象属性和方法的不可更改

// 使用方法:
const arr = [1,2,3,4];
Object.freeze(arr); // 变量arr不可更改
arr.push(5); // 报错:不能添加属性

Object.definePropperty也可以实现规定变量的不可更改

const obj = { key: 'chris', vlaue: 'person' }; 
Object.defineProperty(obj, 'key', { 
  configurable: false, // 不可删除 
  writable: false, // 不可写 });
})

若有不足请多多指教!希望给您带来帮助!

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。如果你想了解更多相关内容请查看下面相关链接

Javascript 相关文章推荐
用js 让图片在 div或dl里 居中,底部对齐
Jan 21 Javascript
jquery.ui.progressbar 中文文档
Nov 26 Javascript
JavaScript实现的使用键盘控制人物走动实例
Aug 27 Javascript
javascript实现瀑布流自适应遇到的问题及解决方案
Jan 28 Javascript
详解javascript遍历方式
Nov 11 Javascript
纯JS代码实现一键分享功能
Apr 20 Javascript
jQuery纵向导航菜单效果实现方法
Dec 19 Javascript
微信小程序获取微信运动步数的实例代码
Jul 20 Javascript
AngularJS 中ui-view传参的实例详解
Aug 25 Javascript
JS实现数组去重及数组内对象去重功能示例
Feb 02 Javascript
vue中get请求如何传递数组参数的方法示例
Nov 08 Javascript
用js编写留言板
Mar 17 Javascript
jQuery无冲突模式详解
Jan 17 #jQuery
JQuery判断radio单选框是否选中并获取值的方法
Jan 17 #jQuery
React性能优化系列之减少props改变的实现方法
Jan 17 #Javascript
vue 项目接口管理的实现
Jan 17 #Javascript
详解VUE单页应用骨架屏方案
Jan 17 #Javascript
Jquery获取radio选中值实例总结
Jan 17 #jQuery
js中call()和apply()改变指针问题的讲解
Jan 17 #Javascript
You might like
php visitFile()遍历指定文件夹函数
2010/08/21 PHP
php中定时计划任务的实现原理
2013/01/08 PHP
PHP对MongoDB[NoSQL]数据库的操作
2013/03/01 PHP
php对图像的各种处理函数代码小结
2013/07/08 PHP
[推荐]javascript 面向对象技术基础教程
2009/03/03 Javascript
document.getElementById介绍
2011/09/13 Javascript
jQuery实现Twitter的自动文字补齐特效
2014/11/28 Javascript
javascript基础知识分享之类与函数化
2016/02/13 Javascript
Angular.js中用ng-repeat-start实现自定义显示
2016/10/18 Javascript
js中开关变量使用实例
2017/02/24 Javascript
javascript实现日期三级联动下拉框选择菜单
2020/12/03 Javascript
浅谈AngularJS中使用$resource(已更新)
2017/09/14 Javascript
用React-Native+Mobx做一个迷你水果商城APP(附源码)
2017/12/25 Javascript
vue-devtools的安装步骤
2018/04/23 Javascript
Vue2.0中三种常用传值方式(父传子、子传父、非父子组件传值)
2018/08/16 Javascript
layer弹出的iframe层在执行完毕后关闭当前弹出层的方法
2018/08/17 Javascript
使用JS监听键盘按下事件(keydown event)
2019/11/07 Javascript
[01:19:34]2014 DOTA2国际邀请赛中国区预选赛 New Element VS Dream time
2014/05/22 DOTA
[51:53]DOTA2-DPC中国联赛 正赛 RNG vs Dragon BO3 第二场 1月24日
2021/03/11 DOTA
python发腾讯微博代码分享
2014/01/10 Python
跟老齐学Python之Python文档
2014/10/10 Python
Python实现朴素贝叶斯分类器的方法详解
2018/07/04 Python
Python多线程原理与用法实例剖析
2019/01/22 Python
Html5实现首页动态视频背景的示例代码
2019/09/25 HTML / CSS
trivago美国:全球最大的酒店价格比较网站
2018/01/18 全球购物
自荐信包含哪些内容
2013/10/30 职场文书
团队经理竞聘书
2014/03/31 职场文书
捐资助学倡议书
2014/04/15 职场文书
幼儿园家长安全责任书
2014/07/22 职场文书
2014年社区国庆节活动方案
2014/09/16 职场文书
2014年党员自我评议对照检查材料
2014/09/20 职场文书
工伤事故处理协议书怎么写
2014/10/15 职场文书
2014年乡镇党建工作总结
2014/11/11 职场文书
2015年三八妇女节活动总结
2015/02/06 职场文书
党员干部学习心得体会
2016/01/23 职场文书
使用CSS自定义属性实现骨架屏效果
2022/06/21 HTML / CSS