什么是数据响应式

“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码。例如,视图渲染中使用了数据,数据改变后,视图也会自动更新。
要点:追踪数据的变化,在读取数据或者设置数据时能劫持一些操作

Vue2使用Object.defineProperty实现响应式

  1. var obj = {}
  2. var age
  3. Object.defineProperty(obj, 'age', {
  4. get: function(){
  5. console.log('get age...')
  6. return age
  7. },
  8. set: function(val){
  9. console.log('set age...')
  10. age = val
  11. }
  12. })
  13. obj.age = 100 // 'set age...'
  14. console.log(obj.age) // 'get age...', 100

总结来说就是,object.definePropety会把数据改为getter和setter。当读取数据的时候调用get,设置数据的时候调用set。同时还能在get和set中写入一些对数据的操作从而监听数据的变化,触发页面渲染。

Vue3使用Proxy实现响应式

Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(例如属性查找、赋值、枚举、函数调用等)

Reflect是一个内置的对象,它提供拦截JS操作的方法

  1. const dinner = {
  2. meal: 'tacos'
  3. }
  4. const handler = {
  5. get(target, prop) {
  6. console.log('get...', prop)
  7. //return target[prop]
  8. return Reflect.get(...arguments)
  9. },
  10. set(target, key, value) {
  11. console.log('set...', key, value)
  12. //target[key] = value
  13. return Reflect.set(...arguments)
  14. }
  15. }
  16. const proxy = new Proxy(dinner, handler)
  17. console.log(proxy.meal)

区别

Vue2的响应式中,如果给data添加新的属性,那么这个新的属性就不会被追踪拦截(不是响应式)。需要使用Vue.set或者this.$set把属性创建并添加代理才会响应式

而Vue3的响应式中,给data添加新属性也会被拦截监听(是响应式的)

总结来说就是:
Proxy能劫持整个对象,⽽Object.defineProperty只能 劫持对象的属性;前者递归返回属性对应的值的代理 即可实现响应式,后者需要深度遍历每个属性;后者 对数组的操作很不友好