1.生命周期
vue2中的写法,在vue3中依然可以这么写。
注意beforeDestroy在vue3变成了beforeUnmount,destroyed变成了unmounted
export default {
/*
data() {
return {
count: 1,
};
},
beforeCreate() {
console.log('beforeCreate');
},
created() {
// 到了这个阶段,数据已经准备好了
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
// 到了这个阶段,页面已经挂载完成了
console.log('mounted');
},
beforeUpdate() {
console.log('beforeUpdate');
},
updated() {
// 到了这个阶段,数据修改了并且页面重新挂载完成了
console.log('updated');
},
beforeUnmount() {
console.log('beforeUnmount');
},
unmounted() {
// 到了这个阶段,组件卸载完毕
console.log('unmounted');
},
*/
}
在组合式api(setup)中使用生命周期
setup可以当成:beforeCreate 和 created,所以setup本身也可以当成一个生命周期函数,并且
setup的执行时机在 beforeCreate 之前。
注意:如果即写了组合式API生命周期函数,又写了传统的生命周期函数,那么组合式API生命周
期函数会先执行。
setup() {
onBeforeMount(()=>{
console.log('onBeforeMount');
})
onMounted(()=>{
console.log('onMounted');
})
onBeforeUpdate(()=>{
console.log('onBeforeUpdate');
})
onUpdated(()=>{
console.log('onUpdated');
})
onBeforeUnmount(()=>{
console.log('onBeforeUnmount');
})
onUnmounted(()=>{
console.log('onUnmounted');
})
}
2.Hook函数
vue3的hook函数有点类似vue2的mixin,两者都能提高代码的可复用性,让我们不需要一种业务重复
写很多次,但是vue3的hook是函数,能够让我们在想要的组件中使用时可以直接引入并使用,代
码来源更加清晰,修改起来也更加方便。
这是许多业务代码写在一起,虽然比起vue2一个业务被拆分成许多块不同,它的业务可以写在一
起,方便修改,但是却显得很臃肿。
import {computed, ref} from 'vue'
export default {
setup() {
//手机相关业务
const phoneName = ref('小米')
const phonePrice = ref(8000)
const phoneZkPrice = computed(()=>{
return (phonePrice.value*0.8).toFixed(2)
})
const updatePhoneName = ()=>{
phoneName.value = '华为'
}
const updatePhonePrice = ()=>{
phonePrice.value = 6000
}
//汽车相关业务
const carName = ref('宝马')
const carPrice = ref(30)
const carZkPrice = computed(()=>{
return (carPrice.value*0.8).toFixed(2)
})
const updateCarName = ()=>{
carName.value = '奔驰'
}
const updateCarPrice = ()=>{
carPrice.value = 40
}
//飞机相关业务
const planeName = ref('F747')
const planePrice = ref(300)
const planeZkPrice = computed(()=>{
return (planePrice.value*0.8).toFixed(2)
})
const updatePlaneName = ()=>{
planeName.value = 'F404'
}
const updatePlanePrice = ()=>{
planePrice.value = 400
}
return {
phoneName,
phonePrice,
phoneZkPrice,
updatePhoneName,
updatePhonePrice,
carName,
carPrice,
carZkPrice,
updateCarName,
updateCarPrice,
planeName,
planePrice,
planeZkPrice,
updatePlaneName,
updatePlanePrice
}
}
}
这是用hook函数写的,很明显结构很清晰,后期也很好维护。
car模块
import {ref,computed} from 'vue'
export default function(){
//汽车相关业务
const carName = ref('宝马')
const carPrice = ref(30)
const carZkPrice = computed(()=>{
return (carPrice.value*0.8).toFixed(2)
})
const updateCarName = ()=>{
carName.value = '奔驰'
}
const updateCarPrice = ()=>{
carPrice.value = 40
}
return {
carName,
carPrice,
carZkPrice,
updateCarName,
updateCarPrice
}
}
phone模块
import {ref,computed} from 'vue'
export default function(){
//手机相关业务
const phoneName = ref('小米')
const phonePrice = ref(8000)
const phoneZkPrice = computed(()=>{
return (phonePrice.value*0.8).toFixed(2)
})
const updatePhoneName = ()=>{
phoneName.value = '华为'
}
const updatePhonePrice = ()=>{
phonePrice.value = 6000
}
return {
phoneName,
phonePrice,
phoneZkPrice,
updatePhoneName,
updatePhonePrice
}
}
plane模块
import {ref,computed} from 'vue'
export default function(){
//飞机相关业务
const planeName = ref('F747')
const planePrice = ref(300)
const planeZkPrice = computed(()=>{
return (planePrice.value*0.8).toFixed(2)
})
const updatePlaneName = ()=>{
planeName.value = 'F404'
}
const updatePlanePrice = ()=>{
planePrice.value = 400
}
return {
planeName,
planePrice,
planeZkPrice,
updatePlaneName,
updatePlanePrice
}
}
导入hook函数并使用
// 导入相关业务的hook函数
import useCar from "@/use/useCar"
import usePhone from "@/use/usePhone"
import usePlane from "@/use/usePlane"
export default {
setup() {
return {
// 展开usePhone函数返回的对象
...usePhone(),
...useCar(),
...usePlane()
}
}
3.toRef和toRefs
import { reactive,toRef,toRefs } from 'vue'
export default {
setup() {
// 定义数据
let stuData = reactive({
name:'张三',
age:20,
car:{
name:'大众',
price:'20W'
}
})
return{
// toRef()函数,可以用来为一个 reactive 对象的属性创建一个 ref
// 这样做的好处是,简化了模板中的表达式。
// toRef()函数,需要传两个参数:1.reactive 对象,2.具体的属性名
// name:toRef(stuData,'name'),
// age:toRef(stuData,'age'),
// car:toRef(stuData,'car')
// 假如 reactive 对象中,有100个属性,上面的操作要写100次,所以,一般都直接用toRefs函数
// toRefs函数,把一个响应式对象转换成普通对象,该普通对象的每个 属性 都是一个 ref
...toRefs(stuData)
}
}
}
4.其他的组合式API
readonly函数:用于定义只读的代理对象, 注意:只读是深层次的,对象本身不能改,对象里面的
属性也不能改。
const car = readonly({
no:'1001',
name:'大众',
color:'白色',
price:30,
type:{
name:'SUV',
level:'中级'
}
})
shallowRef函数:用于定义一个浅响应式的ref对象。 shallowRef() 返回的对象 value 属性值是
object对象(普通对象),不再具备任何响应式了。
const stu2 = shallowRef({
name:'小明',
age:20
})
const updateStu2 = ()=>{
// 直接修改value是具备响应式的
stu2.value = {
name:'小芳',
age:30
}
}
const updateStu2Name = ()=>{
// 修改value里面的具体属性值是不具备响应式
stu2.value.name = '小红'
}
shallowReactive函数:返回一个浅层的响应式代理,只对对象的第一层属性创建响应式
const stu2 = shallowReactive({
name:'小米',
age:22,
friend:{
name:'BY2',
age:20,
car:{
name:'奔驰',
price:20
}
}
})
shallowReadonly函数: 用于定义浅只读对象,不能修改对象的第一层属性,可以修改对象的深层
次属性,注意:修改深层次属性后不会报错,但是不具备响应式效果
const stu3 = shallowReadonly({
name:'李四',
age:22,
friend:{
name:'王五',
age:23
}
})
isRef函数:判断一个对象是否是ref对象
isReactive函数:检查一个对象是否是由 reactive 创建的响应式代理
isReadonly函数:检查一个对象是否是由 readonly 创建的只读代理
isProxy函数 :检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
toRaw函数:将代理对象转为一个普通对象返回
// obj是一个普通对象
let obj = {
name: "张三",
age: 20,
};
// 通过reactive方法,给obj返回一个代理对象
const stu1 = reactive(obj);
// toRaw方法,将一个代理对象转为一个普通对象
// 这个普通对象,就是被代理的对象
const stu2 = toRaw(stu1);
markRaw函数:包装过后的对象,再也不能成为响应式对象,原理是:markRaw方法,会给源对
象添加一个 __v_skip: true属性