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 相关文章推荐
颜色选择器 Color Picker,IE,Firefox,Opera,Safar
Nov 25 Javascript
用JavaScript修改CSS属性的代码
May 06 Javascript
js取消单选按钮选中示例代码
Nov 14 Javascript
angularjs 处理多个异步请求方法汇总
Jan 06 Javascript
Jquery操作Ajax方法小结
Nov 29 Javascript
JQuery EasyUI Layout 在from布局自适应窗口大小的实现方法
May 28 Javascript
jquery.validate使用详解
Jun 02 Javascript
jQuery中on方法使用注意事项详解
Feb 15 Javascript
Node.js利用debug模块打印出调试日志的方法
Apr 25 Javascript
为你的微信小程序体积瘦身详解
May 20 Javascript
使用Node.js搭建静态资源服务详细教程
Aug 02 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
Sep 04 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
启用Csrf后POST数据时出现的400错误
2015/07/05 PHP
使用PHP生成图片的缩略图的方法
2015/08/18 PHP
[原创]php实现子字符串位置相互对调互换的方法
2016/06/02 PHP
(推荐一个超好的JS函数库)S.Sams Lifexperience ScriptClassLib
2007/04/29 Javascript
JS 屏蔽键盘不可用与鼠标右键不可用的方法
2013/11/18 Javascript
深入理解JavaScript高级之词法作用域和作用域链
2013/12/10 Javascript
推荐25个超炫的jQuery网格插件
2014/11/28 Javascript
jQuery实现在最后一个元素之前插入新元素的方法
2015/07/18 Javascript
jQuery拖动布局其结果保存到数据库
2015/10/09 Javascript
javascript倒计时效果实现
2015/11/12 Javascript
js实现点击图片自动提交action的简单方法
2016/10/16 Javascript
Javascript实现图片懒加载插件的方法
2016/10/20 Javascript
JS声明式函数与赋值式函数实例分析
2016/12/13 Javascript
js实现三级联动效果(简单易懂)
2017/03/27 Javascript
Three.js中网格对象MESH的属性与方法详解
2017/09/27 Javascript
微信小程序实现给嵌套template模板传递数据的方式总结
2017/12/18 Javascript
详解JS转换数值函数Number()、parseInt()、parseFloat()
2018/08/24 Javascript
js实现移动端tab切换时下划线滑动效果
2019/09/08 Javascript
vue遍历生成的输入框 绑定及修改值示例
2019/10/30 Javascript
[14:56]教你分分钟做大人:巫医
2014/10/30 DOTA
python控制台显示时钟的示例
2014/02/24 Python
Python实现获取网站PR及百度权重
2015/01/21 Python
使用Python编写基于DHT协议的BT资源爬虫
2016/03/19 Python
Python 递归函数详解及实例
2016/12/27 Python
python xlsxwriter库生成图表的应用示例
2018/03/16 Python
python Jupyter运行时间实例过程解析
2019/12/13 Python
Python使用pdb调试代码的技巧
2020/05/03 Python
Python基础教程之输入输出和运算符
2020/07/26 Python
如何使用pycharm连接Databricks的步骤详解
2020/09/23 Python
python实现图片转字符画
2021/02/19 Python
从Pytorch模型pth文件中读取参数成numpy矩阵的操作
2021/03/04 Python
土耳其国际性时尚购物网站:Modanisa
2018/01/19 全球购物
mysql_pconnect()和mysql_connect()有什么区别
2012/05/25 面试题
如何用Lucene索引数据库
2016/02/23 面试题
迟到检讨书300字
2014/02/14 职场文书
汽车销售经理岗位职责
2014/06/09 职场文书