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 面向对象 function类
May 13 Javascript
JavaScript Accessor实现说明
Dec 06 Javascript
让复选框只能选择一项的方法
Oct 08 Javascript
wap浏览自动跳转到wap页面的js代码
May 17 Javascript
js实现新浪微博首页效果
Oct 16 Javascript
JS中的作用域链
Mar 01 Javascript
JS实现简易换图时钟功能分析
Jan 04 Javascript
jQuery实现数字华容道小游戏(实例代码)
Jan 16 jQuery
JS快速实现简单计算器
Apr 08 Javascript
vue v-for 点击当前行,获取当前行数据及event当前事件对象的操作
Sep 10 Javascript
VUE+Element实现增删改查的示例源码
Nov 23 Vue.js
pnpm对npm及yarn降维打击详解
Aug 05 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实现的浏览器检查类
2016/04/11 PHP
PHP简单实现无限级分类的方法
2016/05/13 PHP
PHP实现创建一个RPC服务操作示例
2020/02/23 PHP
通用于ie和firefox的函数 GetCurrentStyle (obj, prop)
2006/12/27 Javascript
jquery一般方法介绍 入门参考
2011/06/21 Javascript
iframe异步加载实现点击左边菜单加载右边内容实例讲解
2013/03/04 Javascript
jQuery中实现动画效果的基本操作介绍
2013/04/16 Javascript
jquery导航制件jquery鼠标经过变色效果示例
2013/12/05 Javascript
javascript常用函数归纳整理
2014/10/31 Javascript
js中的事件捕捉模型与冒泡模型实例分析
2015/01/10 Javascript
创建你的第一个AngularJS应用的方法
2015/06/16 Javascript
JavaScript String(字符串)对象的简单实例(推荐)
2016/08/31 Javascript
vue.js 使用v-if v-else发现没有执行解决办法
2017/05/15 Javascript
Vue匿名插槽与作用域插槽的合并和覆盖行为
2019/04/22 Javascript
[03:55]显微镜下的DOTA2特别篇——430灰烬之灵神级操作
2014/06/24 DOTA
浅谈pyhton学习中出现的各种问题(新手必看)
2017/05/17 Python
Python将多个excel文件合并为一个文件
2018/01/03 Python
python Django中models进行模糊查询的示例
2019/07/18 Python
Python读写操作csv和excle文件代码实例
2020/03/16 Python
如何在VSCode下使用Jupyter的教程详解
2020/07/13 Python
Nike台湾官方商店:Nike.com (TW)
2017/08/16 全球购物
美国眼镜网站:LensCrafters
2020/01/19 全球购物
P D PAOLA法国官网:西班牙著名的珠宝首饰品牌
2020/02/15 全球购物
size?荷兰官方网站:英国高级运动鞋精品店
2020/07/24 全球购物
幼儿园春游活动方案
2014/01/19 职场文书
党员对十八届四中全会的期盼思想汇报范文
2014/10/17 职场文书
2015年财务科工作总结范文
2015/05/13 职场文书
2015年城乡环境综合治理工作总结
2015/07/24 职场文书
2019年思想汇报
2019/06/20 职场文书
zabbix监控mysql的实例方法
2021/06/02 MySQL
简单总结SpringMVC拦截器的使用方法
2021/06/28 Java/Android
Python人工智能之混合高斯模型运动目标检测详解分析
2021/11/07 Python
redis的list数据类型相关命令介绍及使用
2022/01/18 Redis
教你使用VS Code的MySQL扩展管理数据库的方法
2022/01/22 MySQL
一篇文章弄清楚Ajax请求的五个步骤
2022/03/17 Javascript
Mybatis 一级缓存和二级缓存原理区别
2022/09/23 Java/Android