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 相关文章推荐
如何学习Javascript入门指导
Nov 01 Javascript
jquery 使用简明教程
Mar 05 Javascript
jQuery实现仿淘宝带有指示条的图片转动切换效果完整实例
Mar 04 Javascript
JS+CSS实现仿msn风格选项卡效果代码
Oct 22 Javascript
jquery if条件语句的写法
May 19 Javascript
基于bootstrap按钮式下拉菜单组件的搜索建议插件
Mar 25 Javascript
react 父子组件之间通讯props
Sep 08 Javascript
通过实例了解js函数中参数的传递
Jun 15 Javascript
React路由鉴权的实现方法
Sep 05 Javascript
关于vue路由缓存清除在main.js中的设置
Nov 06 Javascript
Js图片点击切换轮播实现代码
Jul 27 Javascript
vue实现列表拖拽排序的功能
Nov 02 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中的str_repeat函数在JavaScript中的实现
2013/09/16 PHP
php中time()与$_SERVER[REQUEST_TIME]用法区别
2014/11/19 PHP
PHP中使用file_get_contents post数据代码例子
2015/02/13 PHP
浅谈PHPANALYSIS提取关键字
2019/03/08 PHP
Javascript 跨域访问解决方案
2009/02/14 Javascript
js下用层来实现select的title提示属性
2010/02/23 Javascript
js中apply方法的使用详细解析
2013/11/04 Javascript
使用firebug进行调试javascript的示例
2013/12/16 Javascript
关于JS数组追加数组采用push.apply的问题
2014/06/09 Javascript
JS实现转动随机数抽奖特效代码
2020/04/16 Javascript
深入JavaScript高级程序设计之对象、数组(栈方法,队列方法,重排序方法,迭代方法)
2015/12/01 Javascript
AngularJS 路由详解和简单实例
2016/07/28 Javascript
概述VUE2.0不可忽视的很多变化
2016/09/25 Javascript
Bootstrap基本插件学习笔记之Tooltip提示工具(18)
2016/12/08 Javascript
thinkphp标签实现bootsrtap轮播carousel实例代码
2017/02/19 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
[02:46]解说DC:感谢430陪伴我们的DOTA2国际邀请赛岁月
2016/06/29 DOTA
[54:27]TNC vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python使用rsa加密算法模块模拟新浪微博登录
2014/01/22 Python
python中reduce()函数的使用方法示例
2017/09/29 Python
基于Python pip用国内镜像下载的方法
2018/06/12 Python
python用Tkinter做自己的中文代码编辑器
2020/09/07 Python
python爬取天气数据的实例详解
2020/11/20 Python
卡拉威高尔夫官方网站:Callaway Golf
2020/09/16 全球购物
应届大学生求职信
2013/12/01 职场文书
新学期家长寄语
2014/01/19 职场文书
美术指导助理求职信
2014/04/20 职场文书
主题实践活动总结
2014/05/08 职场文书
大跃进口号
2014/06/16 职场文书
优秀班主任推荐材料
2014/12/17 职场文书
2015年检验科工作总结
2015/04/27 职场文书
中学综治宣传月活动总结
2015/05/07 职场文书
2019年最新借条范本!
2019/07/08 职场文书
网络新闻该怎么写?这些写作技巧你都知道吗?
2019/08/26 职场文书
一文读懂go中semaphore(信号量)源码
2021/04/03 Golang
pandas中DataFrame检测重复值的实现
2021/05/26 Python