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中top、clientTop、scrollTop、offsetTop的区别 文字详细说明版
Jan 08 Javascript
基于jquery的loading 加载提示效果实现代码
Sep 01 Javascript
收集json解析的四种方法分享
Jan 17 Javascript
优化RequireJS项目的相关技巧总结
Jul 01 Javascript
AngularJS  自定义指令详解及实例代码
Sep 14 Javascript
Javascript 正则表达式校验数字的简单实例
Nov 02 Javascript
JavaScript代码判断输入的字符串是否含有特殊字符和表情代码实例
Aug 17 Javascript
vue移动端实现红包雨效果
Jun 23 Javascript
JavaScript学习笔记之DOM操作实例分析
Jan 08 Javascript
小程序云函数调用API接口的方法
May 17 Javascript
JS实现容器模块左右拖动效果
Jan 14 Javascript
Vue3为什么这么快
Sep 23 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的错误信息
2006/10/09 PHP
php mysql Errcode: 28 终极解决方法
2009/07/01 PHP
php列出mysql表所有行和列的方法
2015/03/13 PHP
使用新浪微博API的OAuth认证发布微博实例
2015/03/27 PHP
解决PHP里大量数据循环时内存耗尽的方法
2015/10/10 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
YII2框架中使用yii.js实现的post请求
2017/04/09 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
ext checkboxgroup 回填数据解决
2009/08/21 Javascript
css与javascript跨浏览器兼容性总结
2014/09/15 Javascript
jQuery制作可自定义大小的拼图游戏
2015/03/30 Javascript
JS实现根据用户输入分钟进行倒计时功能
2016/11/14 Javascript
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
2016/12/14 Javascript
详解vue的数据binding绑定原理
2017/04/12 Javascript
js实现鼠标拖拽多选功能示例
2017/08/01 Javascript
Node.js中环境变量process.env的一些事详解
2017/10/26 Javascript
javascript函数的节流[throttle]与防抖[debounce]
2017/11/15 Javascript
简单谈谈CommonsChunkPlugin抽取公共模块
2017/12/31 Javascript
JS严格模式知识点总结
2018/02/27 Javascript
Vue中对拿到的数据进行A-Z排序的实例
2018/09/25 Javascript
css配合JavaScript实现tab标签切换效果
2018/10/11 Javascript
vue-quill-editor 自定义工具栏和自定义图片上传路径操作
2020/08/03 Javascript
[00:34]DOTA2上海特级锦标赛 VG战队宣传片
2016/03/04 DOTA
解决pandas 作图无法显示中文的问题
2018/05/24 Python
opencv python 2D直方图的示例代码
2018/07/20 Python
如何在python开发工具PyCharm中搭建QtPy环境(教程详解)
2020/02/04 Python
Python之Django自动实现html代码(下拉框,数据选择)
2020/03/13 Python
百思买加拿大:Best Buy Canada
2018/03/20 全球购物
中国旅游网站:途牛旅游网
2019/09/29 全球购物
实习销售业务员自我鉴定
2013/09/21 职场文书
餐厅筹备计划书
2014/04/25 职场文书
英语辞职信怎么写
2015/02/28 职场文书
Python爬取某拍短视频
2021/06/11 Python
一文教你快速生成MySQL数据库关系图
2022/06/28 Redis
Python测试框架pytest核心库pluggy详解
2022/08/05 Golang
MySQL实现用逗号进行拼接、以逗号进行分割
2022/12/24 MySQL