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对select控件option选项的增删改查示例代码
Oct 21 Javascript
用C/C++来实现 Node.js 的模块(二)
Sep 24 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
Sep 26 Javascript
js中遍历Map对象的方法
Jul 27 Javascript
使用JS代码实现点击按钮下载文件
Nov 12 Javascript
Node.js Express 框架 POST方法详解
Jan 23 Javascript
Vue 2.0学习笔记之Vue中的computed属性
Oct 16 Javascript
Vue中用props给data赋初始值遇到的问题解决
Nov 27 Javascript
Nautil 中使用双向数据绑定的实现
Oct 02 Javascript
15个简单的JS编码标准让你的代码更整洁(小结)
Jul 16 Javascript
基于javascript的无缝滚动动画实现2
Aug 07 Javascript
微信小程序获取当前时间及星期几的实例代码
Sep 20 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桌面中心(一) 创建数据库
2007/03/11 PHP
php ci框架中加载css和js文件失败的原因及解决方法
2014/07/29 PHP
php输出指定时间以前时间格式的方法
2015/03/21 PHP
linux mint下安装phpstorm2020包括JDK部分的教程详解
2020/09/17 PHP
javascript 选择文件夹对话框(web)
2009/07/07 Javascript
ext jquery 简单比较
2010/04/07 Javascript
JavaScript.Encode手动解码技巧
2010/07/14 Javascript
扩展JS Date对象时间格式化功能的小例子
2013/12/02 Javascript
Jquery中的层次选择器与find()的区别示例介绍
2014/02/20 Javascript
javascript解析xml实现省市县三级联动的方法
2015/07/25 Javascript
基于JavaScript实现移除(删除)数组中指定元素
2016/01/04 Javascript
js+canvas绘制矩形的方法
2016/01/28 Javascript
Bootstrap table使用方法记录
2017/08/23 Javascript
AngularJS基于http请求实现下载php生成的excel文件功能示例
2018/01/23 Javascript
Vue配合iView实现省市二级联动的示例代码
2018/07/27 Javascript
解决Vue中使用keepAlive不缓存问题
2020/08/04 Javascript
H5+css3+js搭建带验证码的登录页面
2020/10/11 Javascript
[07:37]DOTA2-DPC中国联赛2月2日Recap集锦
2021/03/11 DOTA
python元组操作实例解析
2014/09/23 Python
python利用matplotlib库绘制饼图的方法示例
2016/12/18 Python
Python中max函数用于二维列表的实例
2018/04/03 Python
python用户评论标签匹配的解决方法
2018/05/31 Python
用python拟合等角螺线的实现示例
2019/12/27 Python
Python定时任务APScheduler原理及实例解析
2020/05/30 Python
python实现快速文件格式批量转换的方法
2020/10/16 Python
python+openCV对视频进行截取的实现
2020/11/27 Python
CSS3 选择器 基本选择器介绍
2012/01/21 HTML / CSS
浅谈html5 响应式布局
2014/12/24 HTML / CSS
在使用非全零作为空指针内部表达的机器上, NULL是如何定义
2014/11/09 面试题
电子商务专业个人的自我评价
2013/11/19 职场文书
建筑公司文秘岗位职责
2013/11/29 职场文书
会计电算化毕业生自荐信
2014/03/03 职场文书
市场营销毕业生自荐信范文
2014/04/01 职场文书
专家推荐信模板
2014/05/09 职场文书
好习惯伴我成长演讲稿
2014/05/21 职场文书
缓存替换策略及应用(以Redis、InnoDB为例)
2021/07/25 Redis