Vue的响应式原理?Vue2和Vue3有什么区别?

一、什么是 Vue 的响应式

Vue 的核心能力就是 数据变化 → 自动更新视图

例如:

javascript 复制代码
data() {
  return {
    count: 1
  }
}
css 复制代码
<div>{{ count }}</div>

当执行:

ini 复制代码
this.count = 2

页面会自动更新。

这个过程就是 响应式系统

核心流程:

复制代码
数据变化
   ↓
监听数据变化
   ↓
通知依赖更新
   ↓
重新渲染视图

Vue 内部有三个关键角色:

角色 作用
Observer 监听数据
Dep 依赖收集
Watcher 触发更新

二、Vue2 响应式原理(Object.defineProperty)

Vue2 使用:

css 复制代码
Object.defineProperty

劫持对象属性。

示例

javascript 复制代码
let obj = {}

Object.defineProperty(obj, "name", {
  get() {
    console.log("读取")
    return value
  },
  set(newVal) {
    console.log("修改")
    value = newVal
  }
})

当访问:

复制代码
obj.name

会触发

scss 复制代码
get()

当修改:

ini 复制代码
obj.name = "Vue"

会触发

scss 复制代码
set()

Vue 就利用这个机制实现响应式。


Vue2 内部流程

1 数据劫持

Vue 在初始化 data 时:

复制代码
遍历所有属性

给每个属性添加 getter / setter。

伪代码:

javascript 复制代码
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      // 收集依赖
      dep.depend()
      return val
    },
    set(newVal) {
      val = newVal
      // 通知更新
      dep.notify()
    }
  })
}

2 依赖收集

当模板渲染:

复制代码
{{ count }}

会生成一个 Watcher

Watcher 会读取数据:

复制代码
count

触发

objectivec 复制代码
getter

然后:

复制代码
Dep 收集 Watcher

结构:

复制代码
count
  ↓
Dep
  ↓
Watcher

3 数据变化

当执行:

kotlin 复制代码
this.count++

触发:

objectivec 复制代码
setter

然后:

scss 复制代码
Dep.notify()

通知所有 Watcher 更新。

复制代码
Watcher → 重新渲染

三、Vue2 的缺点

Vue2 的响应式有几个问题:

1 不能监听对象新增属性

ini 复制代码
this.obj.age = 18

不会更新。

必须:

kotlin 复制代码
Vue.set(this.obj, "age", 18)

2 不能监听数组下标

kotlin 复制代码
this.arr[1] = 10

不会更新。

必须:

perl 复制代码
splice
push
pop
shift

Vue 重写了数组方法。


3 初始化性能差

Vue2 会:

kotlin 复制代码
递归遍历整个 data

如果数据非常大:

复制代码
初始化慢

四、Vue3 响应式原理(Proxy)

Vue3 使用:

javascript 复制代码
Proxy

代替

css 复制代码
Object.defineProperty

示例:

javascript 复制代码
let obj = { name: "vue" }

let proxy = new Proxy(obj, {
  get(target, key) {
    console.log("读取")
    return target[key]
  },
  set(target, key, value) {
    console.log("修改")
    target[key] = value
    return true
  }
})

Proxy 优势

Proxy 可以拦截:

复制代码
13 种操作

比如:

arduino 复制代码
get
set
deleteProperty
has
ownKeys

所以:

复制代码
新增属性
删除属性
数组下标

都能监听。


Vue3 响应式核心

Vue3 内部有两个核心方法:

track(收集依赖)

scss 复制代码
track(target, key)

当读取数据:

arduino 复制代码
get

收集依赖。


trigger(触发更新)

scss 复制代码
trigger(target, key)

当数据变化:

arduino 复制代码
set

通知更新。


核心结构:

javascript 复制代码
targetMap
  ↓
WeakMap
  ↓
Map
  ↓
Set

结构图:

javascript 复制代码
WeakMap
  target -> Map
              key -> Set(effect)

意思是:

复制代码
对象
  ↓
属性
  ↓
依赖函数

五、Vue2 vs Vue3 区别

对比 Vue2 Vue3
响应式实现 Object.defineProperty Proxy
监听新增属性 不支持 支持
数组下标 不支持 支持
初始化性能 需要递归遍历 按需代理
API Options API Composition API
代码体积 较大 更小
TS支持 一般 非常好

六、Vue3 Composition API(核心变化)

Vue3 新增:

scss 复制代码
setup()

例如:

javascript 复制代码
import { ref } from "vue"

export default {
  setup() {
    const count = ref(0)

    const add = () => {
      count.value++
    }

    return { count, add }
  }
}

优势:

复制代码
逻辑复用更好
代码组织更清晰
TS友好

七、面试最佳回答(推荐说法)

面试时可以这样回答:

Vue 的响应式原理是通过数据劫持和依赖收集实现的。

在 Vue2 中,主要通过 Object.defineProperty 对 data 的属性进行 getter 和 setter 劫持,当数据被读取时进行依赖收集,当数据被修改时通知依赖更新,从而触发视图重新渲染。

Vue2 的缺点是无法监听对象新增属性和数组下标变化,因此需要使用 Vue.set 或重写数组方法。

在 Vue3 中,响应式系统改为使用 Proxy 实现。Proxy 可以拦截更多操作,例如属性新增、删除、数组索引等,因此解决了 Vue2 的很多限制。同时 Vue3 使用 tracktrigger 来进行依赖收集和触发更新,并且性能更好。

此外 Vue3 还引入了 Composition API,使得逻辑复用更加灵活,对 TypeScript 支持更好。

相关推荐
苏武难飞几秒前
分享一个THREE.JS中无限滚动的技巧
前端·javascript·css
bitbrowser3 分钟前
2026 PC端多Chrome账号管理指南:从日常切换到防关联实战
前端·chrome
小陈工11 分钟前
Python Web开发入门(二):Flask vs Django,项目结构大比拼
前端·数据库·python·安全·web安全·django·flask
橘子编程11 分钟前
HTML5 权威指南:从入门到精通
前端·css·vue.js·html·html5
不超限13 分钟前
InfoSuite AS部署Vue项目
前端·javascript·vue.js
程序员小寒14 分钟前
JavaScript设计模式(五):装饰者模式实现与应用
前端·javascript·设计模式
wefly201718 分钟前
零基础上手m3u8live.cn,免费无广告的M3U8在线播放器,电脑手机通用
前端·javascript·学习·电脑·m3u8·m3u8在线播放
晓131323 分钟前
React篇——第四章 React Router基础
前端·javascript·react
Moment23 分钟前
如果想转 AI 全栈?推荐你学一下 Langchain!
前端·后端·面试
cch891827 分钟前
常见布局实现详解(Flex 实战版)
前端·javascript·css