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 Zifa FormValid 0.1表单验证 代码打包下载
Jun 08 Javascript
爆炸式的JS圆形浮动菜单特效代码
Mar 03 Javascript
基于jquery实现漂亮的动态信息提示效果
Aug 02 Javascript
使用jquery mobile做幻灯播放效果实现步骤
Jan 04 Javascript
node.js中的fs.rename方法使用说明
Dec 16 Javascript
jQuery实现可拖拽的许愿墙效果【附demo源码下载】
Sep 14 Javascript
原生js实现ajax方法(超简单)
Sep 20 Javascript
bootstrap实现的自适应页面简单应用示例
Mar 09 Javascript
jQuery实现手机号正则验证输入及自动填充空格功能
Jan 02 jQuery
koa2使用ejs和nunjucks作为模板引擎的使用
Nov 27 Javascript
使用Layer组件弹出多个对话框(非嵌套)与关闭及刷新的例子
Sep 25 Javascript
vue仿ios列表左划删除
Sep 26 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 MySQL应用中使用XOR运算加密算法分享
2011/08/28 PHP
PHP容易忘记的知识点分享
2013/04/30 PHP
Laravel框架实现超简单的分页效果示例
2019/02/08 PHP
PHP lcfirst()函数定义与用法
2019/03/08 PHP
解决extjs在firefox中关闭窗口再打开后iframe中js函数访问不到的问题
2008/11/06 Javascript
利用NodeJS的子进程(child_process)调用系统命令的方法分享
2013/06/05 NodeJs
完美解决IE低版本不支持call与apply的问题
2013/12/05 Javascript
jQuery瀑布流插件Wookmark使用实例
2014/04/02 Javascript
node.js正则表达式获取网页中所有链接的代码实例
2014/06/03 Javascript
Javascript中的包装类型介绍
2015/04/02 Javascript
jQuery获取页面元素绝对与相对位置的方法
2015/06/10 Javascript
SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
2015/12/10 Javascript
JavaScript原生对象常用方法总结(推荐)
2016/05/13 Javascript
Bootstrap学习笔记之css样式设计(2)
2016/06/07 Javascript
详解Vue组件之间的数据通信实例
2017/06/17 Javascript
JS中将多个逗号替换为一个逗号的实现代码
2017/06/23 Javascript
Vue.js中组件中的slot实例详解
2017/07/17 Javascript
本地搭建微信小程序服务器的实现方法
2017/10/27 Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
2017/12/14 Javascript
JS实现动态生成html table表格的方法分析
2018/07/11 Javascript
Vuex,iView UI面包屑导航使用扩展详解
2019/11/04 Javascript
vue+element导航栏高亮显示的解决方式
2019/11/12 Javascript
微信sdk实现禁止微信分享(使用原生php实现)
2019/11/15 Javascript
微信小程序图片自适应实现解析
2020/01/21 Javascript
Python ljust rjust center输出
2008/09/06 Python
python操作xml文件详细介绍
2014/06/09 Python
Python使用pydub库对mp3与wav格式进行互转的方法
2019/01/10 Python
如何使用Python发送HTML格式的邮件
2020/02/11 Python
opencv python在视屏上截图功能的实现
2020/03/05 Python
物业管理专业个人的自我评价
2013/11/19 职场文书
2014基层党员干部学习全国两会心得体会
2014/03/17 职场文书
《庐山的云雾》教学反思
2014/04/22 职场文书
2014年后勤工作总结
2014/11/18 职场文书
清明节随笔
2015/08/15 职场文书
python 如何用terminal输入参数
2021/05/25 Python
Pytorch 如何加速Dataloader提升数据读取速度
2021/05/28 Python