监听一个变量的进步,需要怎么做

监听一个变量的变化,当变量变化时执行某些操作,这类似现在流行的前端框架(例如 React、Vue等)中的数据绑定功能,在数据更新时自动更新 DOM 渲染,那么如何实现数据绑定喃?

本文给出两种思路:

  • ES5 的 Object.defineProperty
  • ES6 的 Proxy

ES5 的 Object.defineProperty

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

——MDN


  1. Object.defineProperty(obj, prop, descriptor) 

其中:

  • obj :要定义属性的对象
  • prop :要定义或修改的属性的名称或 Symbol
  • descriptor :要定义或修改的属性描述符

  1. var user = {  
  2.     name'sisterAn'  
  3.  
  4. Object.defineProperty(user'name', { 
  5.     enumerable: true
  6.     configurable:true
  7.     setfunction(newVal) { 
  8.         this._name = newVal  
  9.         console.log('set: ' + this._name) 
  10.     }, 
  11.     get: function() { 
  12.         console.log('get: ' + this._name) 
  13.         return this._name 
  14.     } 
  15. }) 
  16.  
  17. user.name = 'an' // set: an 
  18. console.log(user.name) // get: an 

如果是完整的对变量的每一个子属性进行监听:


  1. // 监视对象 
  2. function observe(obj) { 
  3.    // 遍历对象,使用 get/set 重新定义对象的每个属性值 
  4.     Object.keys(obj).map(key => { 
  5.         defineReactive(obj, key, obj[key]) 
  6.     }) 
  7.  
  8. function defineReactive(obj, k, v) { 
  9.     // 递归子属性 
  10.     if (typeof(v) === 'object') observe(v) 
  11.      
  12.     // 重定义 get/set 
  13.     Object.defineProperty(obj, k, { 
  14.         enumerable: true
  15.         configurable: true
  16.         get: function reactiveGetter() { 
  17.             console.log('get: ' + v) 
  18.             return v 
  19.         }, 
  20.         // 重新设置值时,触发收集器的通知机制 
  21.         setfunction reactiveSetter(newV) { 
  22.             console.log('set: ' + newV) 
  23.             v = newV 
  24.         }, 
  25.     }) 
  26.  
  27. let data = {a: 1} 
  28. // 监视对象 
  29. observe(data) 
  30. data.a // get: 1 
  31. data.a = 2 // set: 2 

通过 map 遍历,通过深度递归监听子子属性

注意, Object.defineProperty 拥有以下缺陷:

  • IE8 及更低版本 IE 是不支持的
  • 无法检测到对象属性的新增或删除
  • 如果修改数组的 length ( Object.defineProperty 不能监听数组的长度),以及数组的 push 等变异方法是无法触发 setter 的

对此,我们看一下 vue2.x 是如何解决这块的?

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章