一、常用组合式api
setup
vue2中的数据、方法、生命周期等写在setup中
vue2可以调用vue3中的数据;vue3不能读取vue2配置的数据;vue2和vue3不要混用
setup有两种返回方式:
//返回渲染函数(了解)
return ()=>{
return h('h1',"sss")
}
//返回一个对象
return {name,age,sayHellow}
注意:1、setup不能是一个async函数 若被async修饰,返回值不再是对象,而是promise(可以是Promise实例,但是需要Suspense和异步组件的配合。
2、setup的执行时机:beforeCreate之前执行一次,this是undefined
3、setup接收两个参数,prop和context
prop:接收组件外部属性
context:上下文对象 {attrs:接收外部属性中,props未声明的属性,slots:接收插槽,emit:相当于this.$emit}
ref函数
作用:实现数据响应式 defineProperty的getter和setter
原理:将基本数据类型数据加工生成RefImpl引用实现的实例对象(引用对象)
引用类型数据加工成Proxy代理对象(内部引用reactive函数)
reactive函数
作用:定义对象类型的响应式数据
ref和reactive对比
ref定义基本数据类型 reactive定义对象类型数据 ref可定义对象数据类型,内部通过reactive
ref通过object.defineProperty()的get与set实现响应式,reactive通过Proxy实现数据劫持,通过Reflect操作对象数据
ref需要通过value读取数据 reactive不需要
vue2和vue3数据响应式对比
vue2:对象类型:通过Object.defineProperty()读取数据,进行数据劫持
数组类型:通过重写更新数组的一系列方法实现拦截
存在问题:新增属性,删除属性,界面无法更新 解决方法:新增:vue.set/this.$set方法 删除:this.$delete/vue.delete方法
直接通过数据下标修改数组,界面无法更新 解决方法:vue.set/this.$set方法 array.splice方法
vue3:利用window内置构造函数Proxy,拦截对象中任意属性的变化(get,set,deleteProperty),通过Reflect对被代理对象的属性进行操作
vue2需要写根标签,vue3不需要,内部将多个标签包含在Fragment虚拟元素中
vue2中的Vue.prototype为vue3中的app.config.globalProperties
//main.js中定义
const app = createApp(App)
app.use(store).use(router).mount('#app')
app.config.globalProperties.$http=()=>{
console.log("ddd");
}
//组件中使用
import {getCurrentInstance} from "vue"
const {proxy} = getCurrentInstance()
function testhttp(){
proxy.$http()
}
computed
setup(){
let person=reactive({
firstName:"zs",
secondName:"ls",
})
//简写形式
let fullName1=computed(()=>{
return person.firstName+"_"+person.secondName
})
//完整写法
let fullName2=computed({
get(){
return person.firstName+"_"+person.secondName
},
set(value){
person.firstName=value.split("_")[0]
person.secondName=value.split("_")[1]
}
})
return {person,fullName1,fullName2}
}
watch
watch(监视对象,回调函数,配置对象)
setup(){
let sum=ref(0)
let msg=ref("whh")
let person=reactive({
name:"zs",
age:18,
job:{
a:{
b:20
}
}
})
// 1、监视ref定义的一个基本数据类型
watch(sum,(newvalue,oldvalue)=>{
console.log("新值为"+newvalue,"旧值为"+oldvalue);
},{immediate:true})
// 2、监视ref定义的多个基本数据类型
watch([sum,msg],(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue);
},{immediate:true})
// 3、监视reactive定义的一个对象 拿不到旧值,且不需要配置deep已经深度监视了,无法关闭
watch(person,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue);
})
// 4、监视reactive定义对象的某一个属性
watch(()=>person.age,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue);
})
// 5、监视reactive定义对象的某些属性
watch([()=>person.name,()=>person.age],(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue);
})
// 6、特殊情况 监视reactive定义对象中的某个对象属性时,需要开启深度监视
watch(()=>person.job,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue);
},{deep:true})
return {sum,msg,person}
}
watchEffect
不需要指明监视哪个属性,监视的回调中使用到哪个属性,就监视哪个属性
与computed对比:computed更注重计算出来的值,需要return
watchEffect更注重回调函数的执行,不需要return
setup(){
let sum=ref(0)
let msg=ref("whh")
let person=reactive({
name:"zs",
age:18,
job:{
a:{
b:20
}
}
})
// 1、监视ref定义的一个基本数据类型
watchEffect(()=>{
const x1=sum.value
const x2=person.job.a.b
console.log("watchEffect执行了");
})
return {sum,msg,person}
}
vue3生命周期
几乎与vue2相同,卸载除外,vue2中的beforeDestory改为beforeUnmount,Destoryed改为Unmounted
使用方式:通过配置项形式使用(与vue2相同)
通过组合式api在setup中使用:
beforeCreate=>setup()
create=>setup()
beforeMount=>onBeforeMount
mounted=>onMounted
beforeUpdate=>onBeforeUpdate
Updated=>onUpdated
beforeUnmount=>onBeforeUnmount
Unmounted=>onUnmounted
同时写的情况同一个生命周期setup中的先执行
自定义hook函数
作用:将setup中使用的组合式api进行封装,实现复用
toRef toRefs
作用:创建一个ref对象,将其value指向另一个对象中的某个属性
const 属性=toRef(对象,“属性”)
const 对象=toRefs(对象)
二、其他组合式api
shallowReactive:和reactive的区别:只处理对象最外层属性的响应式
shallowRef:和ref的区别:只处理基本数据类型的响应式,不进行对象的响应式处理
readonly:响应式数据变为只读(深只读)
shallowReadonly:响应式数据变为只读(浅只读)
toRaw:将reactive生成的响应式对象转为普通对象
markRaw: 标记一个对象,使其永远不会成为响应式对象
customRef:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制
provide和inject:实现祖孙间通信,父组件provide提供数据,子组件inject来使用
provide(“提供的属性名”,属性) inject(“提供的属性名”)
判断响应式数据:
isRef:检查一个值是否为ref对象
isReactive:检查一个对象是否为reactive创建的对象
isReadonly:检查一个对象是否是由readonly创建的只读代理
isProxy:检查一个对象是否由reactive或者readonly方法创建的代理
三、新的组件
Fragment:虚拟容器
Teleport:将内容传送到指定容器,<teleport to="body"/to="#id选择器">组件内容
Suspense:
import Child from './components/Child'//静态引入
import {defineAsyncComponent} from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child'))//异步引入
<Suspense>
<!-- 异步加载组件 -->
<template v-slot:default>
<Child/>
</template>
<!-- 异步组件未展示时显示的界面 -->
<template v-slot:fallback>
<h1>加载中...</h1>
</template>
</Suspense>