vue2响应式原理
Vue2是借助Object.defineProperty()实现的,而Vue3是借助Proxy实现的- 想深入学习
 Vue2的响应式原理, 需要先学习Object.defineProperty()方法- 为了称呼方便, 后续说
 Vue响应式原理统一指Vue2的响应式原理
1.Object.defineProperty 方法 - 简介
- 定义一个对象 
obj, 需要具备name/age等属性 - 当 
age变化时, 在控制台打印最新的值 - 当访问 
obj.age时, 控制台会显示xxx读取了age属性 
演示
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="box">
    <p></p>
    <button id="btn">修改年龄</button>
  </div>
  <script>
    const obj = {
      name: 'zs'
    }
    Object.defineProperty(obj, 'age', {
      // 访问 obj.age 时这个方法会自动执行
      get() {
        console.log('有人访问了 age !', temp)
        return 18
      },
      // 给 obj.age 赋值时这个方法会自动执行, 我们也称之为拦截
      set(newVal) {
        console.log(newVal)
      } 
    })
    
    document.querySelector('p').innerHTML = `${ obj.name } --- ${ obj.age }`
    document.querySelector('#btn').onclick = function() {
      obj.age = 20
    }
  </script>
</body>
</html>
 
总结
- 使用 
Object.defineProperty()可以无痕的监视到对象的属性什么时候发生变化, 什么时候被访问 
2.Object.defineProperty 方法 - 利用临时变量来中转
- 使用了 
Object.defineProperty()后发现get/set并不好用 - 无法设置数据, 同时也不能获取到变化的属性
 
解决方法
-  
定义一个临时变量来中转
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="box"> <p></p> <button id="btn">修改年龄</button> </div> <script> const obj = { name: 'zs' } let temp = 18 Object.defineProperty(obj, 'age', { // 访问 obj.age 时这个方法会自动执行 get() { // 一般会在这里收集依赖, 例如: 网页中 p / h1 / div 等标签要渲染 age 数据 // 注意: 这里是收集这些依赖, 下面会在 set 中自动通知这些依赖来更新 DOM console.log('有人访问了 age !', temp) return temp }, // 给 obj.age 赋值时这个方法会自动执行, 我们也称之为拦截 set(newVal) { // 一般当数据变更时, 通知依赖项更新 DOM console.log(newVal) temp = newVal } }) document.querySelector('p').innerHTML = `${ obj.name } --- ${ obj.age }` document.querySelector('#btn').onclick = function() { obj.age ++ } </script> </body> </html> -  
通过定义一个临时变量作为中转, 可以让
get/set方法用起来就像普通属性去获取 / 修改 
3.Object.defineProperty 方法 - 使用闭包进行封装 defineReactive 函数
- 利用闭包, 来封装一个方法
 val局部变量被内层函数get/set使用, 形成了闭包
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="box">
    <p></p>
    <button id="btn">修改年龄</button>
  </div>
  <script>
    const obj = {
      name: 'zs'
    }
    function defineReactive(obj, key, val) {
      Object.defineProperty(obj, key, {
        // 访问 obj.age 时这个方法会自动执行
        get() {
          // 一般会在这里收集依赖, 例如: 网页中 p / h1 / div 等标签要渲染 age 数据
          // 注意: 这里是收集这些依赖, 下面会在 set 中自动通知这些依赖来更新 DOM
          console.log(`有人访问了 ${ key } !`, val)
          return val
        },
        // 给 obj.age 赋值时这个方法会自动执行, 我们也称之为拦截
        set(newVal) {
          // 一般当数据变更时, 通知依赖项更新 DOM
          console.log(newVal)
          val = newVal
        } 
      })
    }
    defineReactive(obj, 'age', 18)
    
    document.querySelector('p').innerHTML = `${ obj.name } --- ${ obj.age }`
    document.querySelector('#btn').onclick = function() {
      obj.age ++
    }
  </script>
</body>
</html>
 
总结
- 通过利用闭包的特性, 封装一个函数, 可以很好的定义对象的「响应式属性」
 - 将来 
Vue就是利用这一特性, 来实现的响应式原理 
4. 响应式原理 - 简介

讲解
- Vue 响应式核心就是利用了两个类, 
Dep类和Watcher类 - 每个定义在 
data中的数组、对象中都会有一个dep属性,访问属性的时候get方法会收集对应的Watcher 

总结
- 初始化 
data的时候, 调用observe()方法给data里的属性定义get方法和set方法 - 渲染真实 DOM 的时候, 
Watcher会访问页面上使用的属性变量 - 由于 
Object.defineProperty()的特点, 会自动执行get方法, 给数据的Dep都加上渲染函数,每次修改数据时通知渲染Watcher更新视图 






![[附源码]计算机毕业设计基于Springboot景区直通车服务系统](https://img-blog.csdnimg.cn/1d6cd546f4e8410a9e719d0d6972f46c.png)












