vue3 响应式原理
1、 Vue 3 基于 ES6 的 Proxy 特性来拦截对象的读取(get)和设置(set)操作Proxy 可以拦截对象的任意操作,不仅仅是属性访问。
2、 Vue 3 使用 ref 和 reactive 来创建响应式引用:
ref: 用于创建一个响应式的原始值(如字符串、数字)或响应式对象。reactive: 用于创建一个响应式对象,它会对对象的所有属性进行代理。
3、 Vue 3 使用 effect 函数来跟踪响应式数据的变化。当响应式数据发生变化时,与之相关的副作用(通常是组件的渲染函数或其他观察者)会被重新执行。
vue3和vue2的区别
1.主要区别是响应式原理不同
vue2的defineProperty无法响应新增属性(可以通过this.$set解决)而vue3的Proxy不存在该缺陷。 vue2会把整个data进行递归数据劫持,而vue3只有在用到某个对象时,才进行数据劫持,所以响应式更快并且占内存更小。
虚拟dom优化:Vue3 相比于 Vue2 虚拟DOM 上增加patchFlag字段。
Diff 优化:patchFlag字段帮助 diff 时区分静态节点,以及不同类型的动态节点。一定程度地减少节点本身及其属性的比对。 vue3 和 vue2的虚拟dom的diff算法有什么不同 ? Vue3 的快速 Diff 算法比 Vue2 的双端 Diff 算法效率高,Vue3 提升 Diff 算法性能的关键是根据新旧 dom 序列位置的变化,构造了一个最长递增子序列,从而找到更新前后相对位置不变的节点的位置,最大限度地降低了 dom 移动的次数,从而提升了 Diff 算法的性能。
2.其他api不同
比如生命周期api不同(beforeCreate、created都在setup执行),生命周期名字大部分需要+on
3.写法上的区别
vue3支持ts, vue3可以多根节点。声明响应式变量使用了ref和reactive。
4.异步组件
Vue3 提供Suspense组件,允许程序在等待异步组件时渲染兜底的内容,如 loading ,使用户体验更平滑。使用它,需在模板中声明,并包括两个命名插槽:default和fallback。Suspense确保加载完异步内容时显示默认插槽,并将fallback插槽用作加载状态。 若想在 setup 中调用异步请求,需在 setup 前加async关键字。这时,会受到警告async setup() is used without a suspense boundary。
解决方案:在父页面调用当前组件外包裹一层Suspense组件。(使用场景骨架屏)
生命周期api
对于生命周期来说,整体上变化不大,只是大部分生命周期钩子名称上 + “on”,功能上是类似的。不过有一点需要注意,Vue3 在组合式API(Composition API,下面展开)中使用生命周期钩子时需要先引入,而 Vue2 在选项API(Options API)中可以直接调用生命周期钩子,如下所示。
| vue2 | vue3 | 说明 |
|---|---|---|
| beforeCreate | setup | 组件创建之前,执行初始化任务 |
| created | setup | 组件创建完成,访问数据、获取接口数据 |
| beforeMount | onBeforeMount | 组件挂载之前 |
| mounted | onMounted | 组件挂载完成,DOM已创建,访问数据或DOM元素,访问子组件 |
| beforeUpdate | onBeforeUpdate | 未更新,获取更新前所有状态 |
| updated | onUpdated | 组件挂载完成,DOM已创建,访问数据或DOM元素,访问子组件 |
| beforeDestroy | onBeforeUnmount | 未更新,获取更新前所有状态 |
| destroyed | onUnmounted | 组件销毁之后 |
Tips: setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地去定义。
vue3的值传递
defineProps:子组件接收父组件传来的值
defineEmits:子组件接收父组件传来的方法
defineExpose:子组件暴露自己的属性或方法
- 七种Vue3传值方式 props emit v-model refs provide/inject eventBus vuex/pinia(状态管理工具) Vue3中移除了事件总线,但是可以借助于第三方工具来完成,Vue官方推荐mitt[2]或tiny-emitter[3]
ref和reactive的区别
-
类型支持:
reactive主要用于对象和数组,不支持基本数据类型。ref可以用于基本数据类型和对象/数组。
-
内部处理:
reactive直接代理整个对象,使其所有属性都是响应式的。ref创建一个包含value属性的对象,只有value属性是响应式的。
-
模板中使用:
- 在模板中,
reactive对象的属性可以直接使用,不需要额外的操作。 ref在模板中会自动解构,不需要写.value,但在 JavaScript 中访问ref的值时需要加上.value。
- 在模板中,
-
响应式检测:
- 检测
reactive对象使用isReactive。 - 检测
ref使用isRef。
- 检测
-
类型推断:
reactive对象的类型推断更为直接,因为它直接操作对象本身。ref需要类型断言来帮助 TypeScript 正确推断类型。
-
性能:
reactive对象的性能开销相对较小,因为它只需要一次代理。ref对象在每次访问或修改值时都需要通过value属性,可能会有轻微的性能开销。
在实际应用中,根据数据的使用场景和类型选择 reactive 或 ref。对于对象和数组,通常使用 reactive;对于基本数据类型,或者需要在 JavaScript 和模板中一致地处理的数据,使用 ref
总结来说这种设计允许Vue更好地管理其视图更新,确保当数据变化时,视图能够得到相应的更新。
vue3如何检测一个对象是否是响应式的?
import { reactive, isReactive } from 'vue';
const obj = reactive({ count: 0 });
console.log(isReactive(obj)); // 输出: true
const nonReactiveObj = { count: 0 };
console.log(isReactive(nonReactiveObj)); // 输出: false
在这个例子中,obj 是一个响应式对象,所以 isReactive(obj) 返回 true。而 nonReactiveObj 是一个普通对象,不是响应式的,所以 isReactive(nonReactiveObj) 返回 false。
请注意,isReactive 只适用于检测通过 reactive 函数创建的响应式对象。如果你想要检测一个对象是否是由 ref 创建的响应式引用,你应该使用 isRef 函数。如果你想要检测一个对象是否是响应式的(无论是通过 reactive 还是 ref 创建的),你可以使用 isProxy 函数。
import { reactive, isProxy } from 'vue';
const state = reactive({ count: 0 });
console.log(isProxy(state)); // 输出: true
console.log(isProxy({ count: 0 })); // 输出: false
vue3如何获取this
在Vue 3中,获取组件实例的方法有以下几种:
- 在Vue 3中,可以使用
getCurrentInstance函数来获取当前组件的实例。这个函数返回一个ComponentPublicInstance类型的对象,我们可以通过访问这个对象的属性和方法来操作组件。例如:const instance = getCurrentInstance(); - 可以使用Vue 3中的
ref函数来创建一个响应式的变量,然后将组件实例赋值给这个变量。这样可以通过访问这个变量来获取组件实例。例如:const instance = ref(null);,然后在组件的setup函数中使用instance.value = this;来将组件实例赋值给变量。
Vue3中虚拟DOM的diff算法有哪些优化
- Fiber节点: Vue 3引入了Fiber节点树,用于支持异步可中断的渲染。这意味着在更新组件时,Vue可以在执行过程中进行中断,并在需要时继续渲染。(引入Fiber节点树支持异步可中断的渲染)
- 新的diff算法: Vue 3中的diff算法采用了基于键的优化策略,这意味着Vue会尝试复用同一层级内具有相同键的元素。(基于键的优化策略)
- Patch flag: Vue 3为每个组件指定了一个bitmask,用于在diff过程中标记哪些属性发生了变化,这使得Vue可以直接修改那些需要变更的属性,而不是每次都重新渲染整个组件。(指定了一个bitmask标记属性发生了变化)
- Fragment支持: Vue 3支持渲染多个元素或组件而无需包裹在一个外层元素中,这通过Fragment实现。(增加了Fragment抽象组件实现支持多根节点)
- ssr
vue3 有哪些watch 区别是什么
- watch可以精确地监听一个或多个响应式数据
watchEffect:
- 自动监听所有响应式数据:不需要指定具体的数据,所有响应式数据的变化都会触发回调函数。
- 无返回值:回调函数不接受新值和旧值作为参数。
- 执行时机:在组件初始化时立即执行一次,之后在响应式数据变化时再次执行
Vue3,setup()函数与< script setup >到底有什么本质区别
- setup() 自动暴露组件的公共方法和属性
- < script setup > 是语法躺最终还是会转换为setup()
- (插件vite-plugin-inspect可以看穿vue 背后做的事情)