拉开序幕的setup
setup
是Vue3中的一个配置项,它的值是一个函数。setup
是所有Composition API(组合式API)的开始,在Vue2中使用的数据、方法等,都要配置在setup
中,setup
函数有两种返回值:返回一个对象,对象中的属性、方法、在模板中可以直接使用;返回一个渲染函数,可以自定义渲染内容。
在Vue3中,尽量不要与Vue2混用。
Vue2中的配置 (data、methods、computed等)可以访问到setup
中的属性、方法,但是在Vue3中的setup
不能访问到Vue2中的配置(data、methods、computed等)。setup
不能是一个async函数,因为返回值不再是return对象,而是一个promise,模板看不到return对象中的属性,后期可以放回一个Promise实例,但是需要Suspense和异步组件配合。
ref
函数
用于定义一个响应式的数据,就要用到ref
函数。
ref
函数的参数,可以是基本类型,也可以是对象类型。
对于基本数据类型,响应式依赖的是Object.defineProperty()
的get
和set
完成的
对于对象数据类型,响应式依赖的是一个新的函数:reactive()
reactive
函数
用于定义一个对象类型的响应式数据,但是基本数据类型不要使用,基本数据类型,请使用ref()
函数。
内部是基于ES6的Proxy
实现,通过代理对象操作源对象。reactive()
定义的响应式数据是深层次的。
Vue3中的响应式原理
在Vue2中,对象的响应式的实现原理是通过Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持)实现的,数组的响应式是通过重写更新数组的一系列方法来实现拦截的,对数组的变更方法进行了拦截。
存在的问题:
- 新增属性、删除属性,界面不会更新
- 直接铜鼓哦数组下标修改数组,页面不会更新
回顾一下Vue2的响应式,新建Vue2项目。
再来看Vue3的响应式。
原理:
通过Proxy
(代理):拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。
通过Reflect
(反射):对源对象的属性进行操作。
MDN文档中对Proxy
和Reflect
的描述:
Proxy Reflect
reactive
对比ref
- 从定义数据角度对比:
-
ref
用来定义:基本类型数据。 -
reactive
用来定义:对象(或数组)类型数据。 - 备注:
ref
也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive
转为代理对象。
- 从原理角度对比:
-
ref
通过Object.defineProperty()
的get
与set
来实现响应式(数据劫持)。 -
reactive
通过使用Proxy
来实现响应式(数据劫持),并通过Reflect
操作源对象内部的数据。
- 从使用角度对比:
-
ref
定义的数据:操作数据需要.value
,读取数据时模板中直接读取不需要.value
。 -
reactive
定义的数据:操作数据与读取数据:均不需要.value
。
setup
的两个注意点
setup
的执行时机:在beforeCreate
之前执行一次,this的值是undefined。setup
的参数:
- props:值为对象,包含:组件外部传递过来,在组件内部声明接收的属性
- context:上下文对象
- attrs:值为对象,包含:组件外部传递过来,但是没有在props配置里声明的属性,相当于
this.$atrrs
- slots:收到的插槽内容,相当于
this.$slots
- emit:分发自定义事件函数:相当于
this.$emit
App.vue
Demo.vue
计算属性与监视
computed
函数
watch
函数
watchEffect
函数
-
watch
的套路是:既要指明监视的属性,也要指明监视的回调。 -
watchEffect
的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。 watchEffect
有点像computed
:
- 但
computed
注重的计算出来的值(回调函数的返回值),所以必须要写返回值。 - 而
watchEffect
更注重的是过程(回调函数的函数体),所以不用写返回值。
生命周期
Vue2的生命周期:
Vue3的生命周期:
在Vue3中可以继续使用Vue2的生命周期钩子,但是有两个被更名:
beforeDestroy
改名为beforeUnmount
destroyed
改名为unmounted
Vue3也提供了组合式API形式的生命周期钩子,与Vue2中钩子对应关系如下:
-
beforeCreate
=>setup()
-
created
=>setup()
-
beforeMount
=>onBeforeMount
-
mounted
=>onMounted
-
beforeUpdate
=>onBeforeUpdate
-
updated
=>onUpdated
-
beforeUnmount
=>onBeforeUnmount
-
unmounted
=>onUnmounted
Demo.vue
App.vue
自定义hook函数
hook函数本质是一个函数,把setup
函数中使用的组合式API进行了封装
类似于Vue2中的mixin
自定义hook的优势:复用代码,让setup
中的逻辑更清楚易懂
需求:给window绑定一个点击事件,点击一次,在页面输出当前点击的坐标。
Demo.vue
App.vue保持不变。
此时,其他地方,也需要一个打点的功能,方便复用,我们就要用到hook函数,在src目录创建hooks文件夹,创建savePoint.js文件。
savePoint.js
Demo.vue
toRef
作用:创建一个ref对象,其value值指向源对象的某个属性,当创建的这个ref对象修改的时候,源对象的属性值也同步修改。
应用:要将响应式对象中某个属性单独提供给外部使用的时候,而且单独修改这个属性的时候,要求同步修改源数据的属性。
扩展:toRefs
与toRef
功能一致,但是可以批量创建多个ref对象。