Composition API
Composition API 也叫组合式 API,它主要就是为了解决 Vue2 中 Options API 的问题。
vue2中,我们在methods、computed、watch、data中定义属性和方法,共同处理页面逻辑,我们称这种方式为Options API。
这种代码模式下存在几个问题:
- 随着功能的增长,复杂组件的代码变得越来越难以维护。 尤其去新接手别人的代码时。 根本原因是 Vue 的现有 API 通过「选项」组织代码,但是在大部分情况下,通过逻辑考虑来组织代码更有意义。
- 缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制。
- 类型推断不够友好。
Composition API顾名思义就是不再传入data、mounted等参数,通过引入的ref、onMounted等方法实现数据的双向绑定、生命周期函数的执行。Composition API目的是通过一组低侵入式的、函数式的 API,使得我们能够更灵活地「组合」组件的逻辑,因此其中的代码是根据逻辑功能来组织的,同一功能所定义的所有api会放在一起。
setup
vue3中使用setup代替了beforeCreate和created这两个生命周期,setup()是在创建vue组件实例并完成props的初始化之后执行(在 created() 生命周期函数之前执行)。同时setup返回的值,可以在模板和其他option中使用。
1 | setup(props, context){ |
与Vue2区别:
不能使用this,而是通过 context 对象来代替当前执行上下文绑定的对象,context 对象有四个属性:attrs、slots、emit、expose。
ref、reactive
reactive 和 ref 都是用来定义响应式数据的。一般来说,ref用于基础赋值类型的数据,而reactive用于引用类型的数据。ref 的底层就是 reactive。
ref
ref函数传入一个值作为参数,一般传入基本数据类型(原始数据),ref的返回值是一个对象,这个对象上只包含一个.value属性。(可以理解为ref是在reactive上的封装)
- 基本类型数据:响应式依然是通过Object.defineProperty()。
- 引用类型数据:响应式是通过调用内部方法reactive函数(通过Proxy)
reactive
reactive是用来定义更加复杂的数据类型,但是解构就不具备响应式了(相当于跳过了代理重新赋新值了)。
toRef 和 toRefs
toRef是将对象中的某个值转化为响应式数据 toRef(obj, key)。
toRefs函数可以将reactive创建出来的响应式对象转换为普通的对象,这个对象上的每个属性都是Ref类型的响应式数据。
toRef和toRefs是对原始数据的引用,修改响应式数据时,原始数据也会发生改变,但是视图并不会更新。toRef修改的是对象的某个属性,toRefs修改的是整个对象
isRef
判断是否是ref对象。
unref
返回ref的.value值,或返回原值。
watch、watchEffect
watchEffect立即运行一个函数,然后被动的追踪它的依赖,当依赖重新改变时执行该函数。watch监测一个或多个响应式数据,并在变化时调用一个回调函数。
watchEffect是特殊的watch,传入的函数既是数据源又是回调。如果不关心数据变化前后值,只想监听拿到数据执行事件就可以用这个。watch更底层,可以接受多个数据源,可以获取变化前后的值。
watchEffect会立即执行一次,watch默认不会立即执行,除非传入immdiate。
watchEffect与watch区别:
- 不需手动传入依赖
- 初始化时会立即执行
- 无法获取到原值,只能得到变化后的值
watch
watch 作用是监听传值(和Vue2一致,是惰性的,会返回新值和旧值)。
1 | // ref 数据 |
与Vue2区别:
- 传参不一样,watch需要传监听的响应式变量,回调函数,options配置
- 停止监听: 在组件中创建的watch监听,会在组件被销毁时自动停止。如果在组件销毁之前想要停止掉某个监听, 可以调用watch()函数的返回值。
1
2
3
4
5
6
7
8
9
10const watchFun = watch(
name,
(newValue, oldValue) => {},
{ immediate: true, deep: true }
)
setTimeout(()=>{
// 停止监听
watchFun()
}, 3000)
watchEffect
watchEffect用法和watch不一样。watchEffect 是传入一个立即执行函数,所以默认第一次也会执行一次;不需要传入监听内容,会自动收集函数内的数据源作为依赖,在依赖变化的时候又会重新执行该函数,如果没有依赖就不会执行;而且不会返回变化前后的新值和老值。
1 | watchEffect(() => {}) |
生命周期钩子
- setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
- onBeforeMount() : 组件挂载到节点上之前执行的函数。
- onMounted() : 组件挂载完成后执行的函数。
- onBeforeUpdate(): 组件更新之前执行的函数。
- onUpdated(): 组件更新完成之后执行的函数。
- onBeforeUnmount(): 组件卸载之前执行的函数。
- onUnmounted(): 组件卸载完成后执行的函数
- onActivated(): 被包含在keep-alive中的组件,会多出两个生命周期钩子函数。被激活时执行。
- onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
- onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数(以后用到再讲,不好展现)。
Fragment(碎片化节点)
vue3组件的模板结构中出现多个标签时,可以不用根标签。编译时vue会在这些元素节点上添加一个<Fragment></Fragment>标签。并且该标签不会出现在dom树中。
Teleport(传送门)
是一个内置组件,使我们可以将一个组件的一部分模板“传送”到该组件的 DOM 层次结构之外的 DOM 节点中。
使用场景:有时组件模板的一部分逻辑上属于该组件,但元素上最好将模板的这一部分移动到组件之外的其他位置。比如点击按钮出现的弹出框。
1 | // 渲染到body标签下 |
Suspense(异步组件)
vue3中提供一个<Suspense></Suspense>组件用于控制异步组件。
作用:等待异步组件时渲染一些额外内容,让应用有更好的用户体验
使用:
1 | <Suspense> |
其他框架层面的优化
- 更快
- 虚拟DOM重写:
- 编译器优化:静态提升、patchFlags.block等
- 基于Proxy的响应式
- 更小:Tree-shaking优化
- 更好维护:Ts + 模块化
- 更容易扩展
- 独立的响应化模块
- 自定义渲染器


