一. setup
- setup是一个函数
- Vue2.x中可以访问到setup的数据和函数,而setup不能访问Vue2.x,如果重名以setup优先
- setup不能是一个async函数,因为返回值不再是return的对象,而是promise,模板看不到return对象中的属性
二. ref函数
- 定义响应式数据
- 接收数据可以是基本类型和对象类型
- 基本类型的数据响应式依然是依靠Object.defineProperty()的get和set完成的
- 对象类型的数据响应式内部求助了Vue3.0中的一个新函数reactive函数
setup(){
let name = ref('张三')
function log(){
console.log(name.value)
}}
三. reactive函数
- 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
- reactive函数定义的响应式数据是深层次的
- 内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作
四. Vue3.0中响应式原理
-
Vue2.x的响应式
-
实现原理:
普通类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
Object.defineProperty(data,'count',{ get(){}, set(){} })-
存在问题:
新增属性、删除属性界面不会更新。
直接通过下标修改数组,界面不会自动更新。
-
-
Vue3.0的响应式
-
实现原理:
通过Proxy(代理):拦截对象中任意属性的变化,包括:属性的读写、属性的添加、属性的删除等。
通过Reflect(反射):对被代理对象的属性进行操作。
-
五. setup注意点
-
setup执行的时机
在beforeCreate之前执行一次,this是undefind
-
setup的参数
props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
context:上下文对象
attrs:值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性,相当于this.$attrs。
slots:收到的插槽内容,相当于this.$slots。
emit:分发自定义事件的函数,相当于this.$emit。
六. watch函数
-
与Vue2.x中watch配置功能一致
-
两个小“坑”:
- 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
- 监视reactive定义的响应式数据中某个属性时:deep配置有效。
//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
},{immediate:true})
//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
console.log('sum或msg变化了',newValue,oldValue)
})
/* 情况三:监视reactive定义的响应式数据
若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue!!
若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
*/
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不再奏效
//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//情况五:监视reactive定义的响应式数据中的某些属性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//特殊情况
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
七. watchEffect函数
-
watch的套路是:既要指明监视的属性,也要指明监视的回调。
-
watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
-
watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
const x1 = sum.value
const x2 = person.age
console.log('watchEffect配置的回调执行了')
})
八. 生命周期
-
beforeDestroy改名为beforeUnmount -
destroyed改名为unmounted -
Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
beforeCreate===>setup()created=======>setup()beforeMount===>onBeforeMountmounted=======>onMountedbeforeUpdate===>onBeforeUpdateupdated=======>onUpdatedbeforeUnmount==>onBeforeUnmountunmounted=====>onUnmounted
九. 更多Composition API
-
shallowReactive 与 shallowRef
-
readonly 与 shallowReadonly
-
toRaw 与 markRaw
-
toRaw:
- 作用:将一个由
reactive生成的响应式对象转为普通对象。 - 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
- 作用:将一个由
-
markRaw:
-
作用:标记一个对象,使其永远不会再成为响应式对象。
-
应用场景:
- 有些值不应被设置为响应式的,例如复杂的第三方类库等。
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
-
-
-
customRef
作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
-
provide 与 inject
- 作用:实现祖与后代组件间通信
- 套路:父组件有一个
provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据
-
响应式数据的判断
- isRef: 检查一个值是否为一个 ref 对象
- isReactive: 检查一个对象是否是由
reactive创建的响应式代理 - isReadonly: 检查一个对象是否是由
readonly创建的只读代理 - isProxy: 检查一个对象是否是由
reactive或者readonly方法创建的代理
十. 新组件
- Fragment:根标签
- Teleport:组件移动
- Suspense