vue3比vue2的区别在哪,主要有什么优势
Vue2:用 Object.defineProperty 监听对象属性
- 缺点:新增 / 删除属性监听不到、数组下标修改不响应、嵌套对象性能差
Vue3:用 ES6 Proxy 代理整个对象
- 优点:天然支持新增 / 删除属性、数组任意修改都响应、性能更强
ref/reactive
定义变量用来把「普通数据」变成「响应式数据」
- ref 用于 基本类型(数字、字符串、布尔)
- reactive 用于 引用类型(对象、数组)
watch / watchEffect
- 想精准监听 → watch
- 想自动追踪、方便快捷 → watchEffect
API 风格
Vue2:选项式 API(data、methods、computed 分开写) 配置一个页面
Vue3:组合式 API(按业务逻辑组织代码) 写一个页面
<script setup>语法性能更好
模板
Vue2:模板必须只有一个根节点
Vue3:模板可以多个根节点,不用套无用的 div
其他优势
- 打包体积更小(Tree-shaking 更好)
- 更好的 TypeScript 支持
- Vue3 用 自定义 Hook,干净、透明、无副作用。
- Vue3新增的组件传值defineProps defineEmits defineModel
(延申问题) Object.defineProperty 与Proxy 的区别是什么?
Object.defineProperty 只能监听对象的 “某一个属性”; Proxy 能直接监听 “整个对象”。
(延申问题)Proxy 的底层实现逻辑是什么?
- Proxy 是 ES6(ES2015)正式新增的原生语法
- Vue3 不支持 IE 浏览器 因为 Proxy 根本没法降级兼容。
- defineProperty 是提前给每个属性绑监听; Proxy 是监听整个对象的 “操作行为”。
(延申问题)vue2要想实现Proxy 有哪几种方法?
- Vue.set / this.$set(解决新增属性)
- Vue.delete / this.$delete(解决删除属性)
(延申问题)<script setup>的逻辑是什么?
- 它是编译时语法糖,不是运行时新特性
- 所有代码都会被打包进 setup() 函数
- 顶层声明自动暴露给模板,无需 return
- 它是 Vue3 最标准、最推荐的写法
- 本质上是闭包的延申
(延申问题)Tree-shaking 对 Vue2 的优化有哪些:
- 删除你自己写的、未使用的业务代码(最主要)
- 删除未使用的 ES6 第三方库代码(如 lodash-es)
- 删除 Vue2 内部极少的无用模块(几乎没用)
(延申问题)watchEffect 的业务使用场景:
- 多条件搜索、筛选
- 表单联动、多级选择
- 多状态控制按钮权限
- 数据变化自动重新渲染图表
- 初始化 + 变化都要执行的请求
VUE的组件传值
- 父 → 子:props
- 子 → 父:emit
- 父 ↔ 子:v-model /defineModel
- 父 → 子:ref / $parent
- 子 → 父:$attrs / $listeners(爷孙组件透传)
- 兄弟:provide / inject eventBus(VUE3没有)
(延申问题)provide /inject的实现逻辑
原型链查找机制 + 组件树递归向上遍历
(延申问题)provide /inject是响应式的么?怎么实现响应式
本身非响应式,传 ref/reactive 才响应式(因为传递的是地址)
(延申问题)ref 和 reactive 区别
- ref 支持所有类型, reactive 只支持对象数组
- ref 要 .value, reactive 不用
- ref 底层是对象包装, reactive 底层是 Proxy
- reactive 不能直接赋值, ref 可以
- 业务:基本类型用 ref,对象用 reactive
- 解构 reactive 会失去响应式
(延申问题)如何解决解构 reactive 会失去响应式的问题?(本质上是问ref、 toRef、和toRefs的区别)
- ref:创建响应式变量,独立,复制值
- toRef:将对象单个属性转为响应式,关联源对象
- toRefs:将 reactive 对象整体转 ref 集合,用于解构
- toRefs 是 reactive 解构的唯一正确方式
描述vue3的生命周期
- Vue3 把 beforeCreate /created 合并到 setup 里了
- 其他生命周期前面加个 on 就行
- setup() —— 组件创建
- onBeforeMount —— 挂载前
- onMounted —— 挂载完成(发请求、操作 DOM)
- onBeforeUpdate —— 更新前
- onUpdated —— 更新完成
- onBeforeUnmount —— 销毁前
- onUnmounted —— 销毁完成(清除定时器、事件)
(延申问题)Vue3 新增的生命周期(性能 / 调试)
1. onActivated / onDeactivated
keep-alive 缓存组件专用 进入 / 离开缓存组件时触发
2. onErrorCaptured
捕获子组件错误
3. onRenderTracked / onRenderTriggered
调试用,看什么数据触发了渲染
Pinia vs Vuex 的区别
Vuex 核心结构state / getters / mutations / actions / modules | Pinia核心结构state / getters / actions(无 mutations)
1. Pinia 没有 mutations(最关键)
- Vuex: 改数据必须走 commit → mutations(只能同步),异步要走 dispatch → actions。
- Pinia: 直接在 actions 里同步 / 异步随便写,不用绕一层 mutations,代码少一半。
2. 模块化方式完全不同
- Vuex:一个大 store,里面套 modules,命名空间容易乱。
- Pinia:每个模块就是一个独立的 store,直接 import,互不干扰,非常清爽。
3. TypeScript 体验天差地别
- Vuex:类型要自己写、嵌套模块类型难维护。
- Pinia:自动类型推导,写代码全程智能提示,几乎不用写类型。
Vue3 setup中如何获取组件实例(vue2的$ref)
- setup 中没有 this
- 获取 DOM / 子组件:用同名 ref + onMounted 怎么写
- 子组件必须用 defineExpose 暴露方法 / 属性
(最深的问题)getCurrentInstance(获取全局实例)是什么?怎么使用
- getCurrentInstance = 获取当前组件实例
- 可以拿到 proxy(等价 this)
- 官方不推荐业务使用,只用于开发 / 插件
- 业务请用组合式 API:useRouter、useRoute、useStore
- Vue3 最佳实践:忘掉 this
getCurrentInstance 仅供 开发 / 调试 / 插件 / 高级库使用 不推荐在业务代码中使用!