一、定义

vue是通过Object.defineProperty()来实现双向数据绑定的,它作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

  1. Object.defineProperty(obj, prop, desc)
  1. obj 需要定义属性的当前对象
  2. prop 当前需要定义的属性名
  3. desc 属性描述符

二、描述符属性配置

一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。

  1. Object.defineProperty(obj:对象, propkey, descriptor:属性和方法)
  2. let obj = {}
  3. Object.defineProperty(obj,'a',{
  4. configurable: true //是否允许删除
  5. enumerabletrue //是否允许枚举
  6. valueundefined //就是value值
  7. writabletrue //是否允许赋值
  8. get() {} //获取的return的值
  9. set(newVal) {} //修改的时候执行 newVal就是最新的值
  10. })
  1. //区别在于单个截止和多个劫持
  2. Object.defineProperties(obj,{
  3. a:{
  4. get() {
  5. //需要return 否则会返回 undefined
  6. return 1
  7. }
  8. set(newVal) {
  9. //newVal 是给属性 a 最新赋的值
  10. //可以执行函数、dom操作等一些方法
  11. }
  12. },
  13. b:{
  14. get() {}
  15. set() {}
  16. }
  17. })

三、数据读写

读数据,会触发 get,并且 get 内部需要返回数据,才能读取到数据
但是由于 Object.defineProperty 的缺陷,直接在 return 后面 返回 data.name,会进入死循环,所以需要通过一个全局变量进行管理

  1. const data = {
  2. name: '张三',
  3. age: 14
  4. }
  5. let value = data.name
  6. Object.defineProperty(data, 'name', {
  7. get() {
  8. console.log('读数据了')
  9. return value
  10. },
  11. set(val) {
  12. console.log('写数据了')
  13. }
  14. })
  15. console.log(data.name)

四、写数据

  1. const data = {
  2. name: '张三',
  3. age: 14
  4. }
  5. let value = data.name
  6. Object.defineProperty(data, 'name', {
  7. get() {
  8. console.log('读数据了')
  9. return value
  10. },
  11. set(val) {
  12. console.log('写数据了' + val)
  13. value = val
  14. }
  15. })
  16. console.log(data.name)
  17. data.name = '赵四'
  18. console.log(data.name)
  1. // 打印结果
  2. 读数据了
  3. 张三
  4. 写数据了赵四
  5. 读数据了
  6. 赵四

五、单层数据响应

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta
  6. name="viewport"
  7. content="width=device-width, initial-scale=1.0"
  8. />
  9. <title>Document</title>
  10. </head>
  11. <body>
  12. <div>
  13. <p id="name"></p>
  14. <p id="age"></p>
  15. </div>
  16. <script>
  17. // 定义数据
  18. const data = {
  19. name: '张三',
  20. age: 19
  21. }
  22. // 同步视图的方法
  23. function setView() {
  24. document.getElementById('name').innerHTML = data.name
  25. document.getElementById('age').innerHTML = data.age
  26. }
  27. setView()
  28. // 利用循环对数据进行监听
  29. Object.keys(data).forEach(key => {
  30. // 利用外部数据进行数据的读写控制
  31. let getValue = data[key]
  32. Object.defineProperty(data, key, {
  33. // 读数据
  34. get() {
  35. return getValue
  36. },
  37. // 写数据
  38. set(val) {
  39. getValue = val
  40. setView()
  41. }
  42. })
  43. })
  44. </script>
  45. </body>
  46. </html>

六、数据无法响应的情况

https://cn.vuejs.org/v2/guide/reactivity.html

对象:对象新增的数据无法响应