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的函数
Jan 31 Javascript
跟着JQuery API学Jquery 之二 属性
Apr 09 Javascript
浮动的div自适应居中显示的js代码
Dec 23 Javascript
简介JavaScript中的getUTCFullYear()方法的使用
Jun 10 Javascript
JSON键值对序列化和反序列化解析
Jan 24 Javascript
正则 js分转元带千分符号详解
Mar 08 Javascript
vue 1.0 结合animate.css定义动画效果
Jul 11 Javascript
详解vuex状态管理模式
Nov 01 Javascript
小程序简单两栏瀑布流效果的实现
Dec 18 Javascript
windows下create-react-app 升级至3.3.1版本踩坑记
Feb 17 Javascript
基于VUE实现判断设备是PC还是移动端
Jul 03 Javascript
Vue.Draggable实现交换位置
Apr 07 Vue.js
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
1982年日本摄影师镜头下的中国孩子 那无忧无虑的童年
2020/03/12 杂记
怎样去阅读一份php源代码
2009/08/21 PHP
php5.2的curl-bug 服务器被php进程卡死问题排查
2016/09/19 PHP
PHP进阶学习之反射基本概念与用法分析
2019/06/18 PHP
PHP优化之批量操作MySQL实例分析
2020/04/23 PHP
用 Javascript 验证表单(form)中的单选(radio)值
2009/09/08 Javascript
JQuery SELECT单选模拟jQuery.select.js
2009/11/12 Javascript
jQuery插件开发的两种方法及$.fn.extend的详解
2014/01/16 Javascript
js输出阴历、阳历、年份、月份、周示例代码
2014/01/29 Javascript
JavaScript学习笔记之基础语法
2015/01/22 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
jquery弹出遮掩层效果【附实例代码】
2016/04/28 Javascript
Vue 固定头 固定列 点击表头可排序的表格组件
2016/11/25 Javascript
基于jQuery实现弹幕APP
2017/02/10 Javascript
详解Webstorm 新建.vue文件支持高亮vue语法和es6语法
2017/10/26 Javascript
react组件从搭建脚手架到在npm发布的步骤实现
2019/01/09 Javascript
2019 年编写现代 JavaScript 代码的5个小技巧(小结)
2019/01/15 Javascript
JavaScript实现省份城市的三级联动
2020/02/11 Javascript
利用QT写一个极简单的图形化Python闹钟程序
2015/04/07 Python
python脚本替换指定行实现步骤
2017/07/11 Python
python机器学习理论与实战(四)逻辑回归
2018/01/19 Python
Python模块/包/库安装的六种方法及区别
2020/02/24 Python
Pandas时间序列基础详解(转换,索引,切片)
2020/02/26 Python
jupyter notebook运行命令显示[*](解决办法)
2020/05/18 Python
Python confluent kafka客户端配置kerberos认证流程详解
2020/10/12 Python
Python抓包并解析json爬虫的完整实例代码
2020/11/03 Python
会计专业自我鉴定范文
2013/10/06 职场文书
广告学专业推荐信范文
2013/11/23 职场文书
电厂厂长岗位职责
2014/01/02 职场文书
教师评优事迹材料
2014/01/10 职场文书
2014年档案管理员工作总结
2014/12/01 职场文书
2015年世界环境日活动总结
2015/02/11 职场文书
2014年度个人总结范文
2015/03/09 职场文书
毕业生政审意见范文
2015/06/04 职场文书
Python-typing: 类型标注与支持 Any类型详解
2021/05/10 Python
python模板入门教程之flask Jinja
2022/04/11 Python