好看的网页千篇一律,有趣的代码万里挑一。
2022新年好!
关键字:
Vue3高阶\Hook函数\ 生命周期\toRef和toRefs \其他的组合式API
1. Hook函数
useCar
import {ref,computed} from 'vue'
//导出去一个函数
export default function(){
//汽车数据
let carName = ref('保时捷')
let carPrice = ref(100)
//汽车的计算属性
let carPrice2 = computed(()=>{
return (carPrice.value*0.8).toFixed(2)
})
//操作汽车的方法
let updateCar = ()=>{
carName.value = '宾利'
carPrice.value = 300
}
//返回暴露给外界的内容
return {
carName,
carPrice,
carPrice2,
updateCar
}
}
usePhone
import {ref,computed} from 'vue'
export default function(){
//手机数据
let phoneName = ref('华为')
let phonePrice = ref(5000)
//手机的计算属性
let phonePrice2 = computed(()=>{
return (phonePrice.value*0.5).toFixed(2)
})
//操作手机的方法
let updatePhone = ()=>{
phoneName.value = '苹果'
phonePrice.value = 9000
}
//返回暴露给外界的内容
return {
phoneName,
phonePrice,
phonePrice2,
updatePhone
}
}
组件
<h1>Hook函数</h1>
<div class="car">
<h2>汽车信息</h2>
<ul>
<li>汽车名称:{{carName}}</li>
<li>汽车价格:{{carPrice}}万</li>
<li>优惠价格:{{carPrice2}}万</li>
<li>
<button @click="updateCar">修改汽车信息</button>
</li>
</ul>
</div>
<div class="phone">
<h2>手机信息</h2>
<ul>
<li>手机名称:{{phoneName}}</li>
<li>手机价格:{{phonePrice}}</li>
<li>优惠价格:{{phonePrice2}}</li>
<li>
<button @click="updatePhone">修改手机信息</button>
</li>
</ul>
</div>
// 导入hook函数
import useCar from '../hooks/useCar'
import usePhone from '../hooks/usePhone'
export default {
setup() {
// 返回模板中需要使用的数据
return {
//返回汽车信息
...useCar(),
//返回手机信息
...usePhone()
}
}
}
2. 生命周期
变化挺大的:
<h1>生命周期</h1>
<h3>
数量:{{count}}
<button @click="count++">数量++</button>
</h3>
// 组合式API生命周期函数
import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'
export default {
// beforeCreate() {
// console.log('创建之前');
// },
// created() {
// console.log('创建完成');
// },
// beforeMount() {
// console.log('挂载之前1');
// },
// mounted() {
// console.log('挂载完成1');
// },
// beforeUpdate() {
// console.log('更新之前1');
// },
// updated() {
// console.log('更新完成1');
// },
//注意:在vue3中,对beforeDestroy和destroyed这两个生命周期函数,进行了重命名
/* beforeDestroy() {
console.log('销毁之前');
},
destroyed() {
console.log('销毁完成');
}, */
// 在vue3中,beforeUnmount 替换了 beforeDestroy;unmounted 替换了 destroyed
// beforeUnmount() {
// console.log('卸载之前1');
// },
// unmounted() {
// console.log('卸载完成1');
// },
data() {
return {
count:1
}
},
// setup()函数,可以替代beforeCreate 和 created 这两个生命周期函数
setup() {
console.log('setup');
//组合式API生命周期函数,会先与传统的生命周期函数执行
onBeforeMount(()=>{
console.log('挂载之前2');
})
onMounted(()=>{
console.log('挂载完成2');
})
onBeforeUpdate(()=>{
console.log('修改之前2');
})
onUpdated(()=>{
console.log('修改完成2');
})
onBeforeUnmount(()=>{
console.log('卸载之前2');
})
onUnmounted(()=>{
console.log('卸载完成2');
})
}
}
3. toRef和toRefs
<h1>toRef和toRefs</h1>
<div class="stu">
<h2>学生信息</h2>
<ul>
<li>姓名:{{name}}</li>
<li>姓名:{{age}}</li>
<li>车名:{{car.name}}</li>
<li>车价:{{car.price}}</li>
</ul>
</div>
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
<h1>其他的组合式API</h1>
<div>
学生信息:{{stuData}}
<br>
<button @click="stuData.age++">修改年龄</button>
<button @click="stuData.car.price++">修改车价</button>
</div>
<div>
num3的值:{{num3}}
</div>
<div>
汽车信息:{{car}}
<button @click="updateCar">修改汽车</button>
</div>
<div>
手机信息:{{phone}}
<button @click="updatePhone">修改手机</button>
</div>
<div>
年龄:{{age}}
<button @click="age++">年龄++</button>
</div>
import {ref,reactive,readonly,isRef,unref, shallowRef, isReactive, shallowReactive,customRef,toRaw, markRaw} from 'vue'
export default {
setup() {
// 定义数据
// readonly()函数,返回一份只读数据,这个只读是“深层的”,内部任何嵌套的属性也都是只读的
let stuData = readonly({
name:'张三',
age:20,
car:{
name:'大众',
price:20
}
})
let num1 = ref(100)
let num2 = 200
// isRef()函数,检查一个值是否为一个 ref 对象
// isProxy()函数,检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
// isReactive()函数,检查一个对象是否是由 reactive 创建的响应式代理
// isReadonly()函数,检查一个对象是否是由 readonly 创建的只读代理
// let num3 = (isRef(num1)?num1.value:num1) + (isRef(num2)?num2.value:num2)
// unref()函数,如果参数是一个 ref 则返回它的 value,否则返回参数本身
let num3 = unref(num1) + unref(num2)
// ref() 返回的对象 value 属性值是 reactive对象(代理对象)
// shallowRef() 返回的对象 value 属性值是 object对象(普通对象),不再具备任何响应式了
let car = shallowRef({
name:'大众',
type:{
typeName:'SUV'
}
})
let updateCar = ()=>{
// 由于value返回的是object对象,所以,这里不再具有响应式
car.value.name = '奔驰'
car.value.type.typeName = '跑车'
}
// shallowReactive() 返回一个浅层的响应式代理,只对对象的第一层属性创建响应式
let phone = shallowReactive({
name:'华为',
type:{
typeName:'滑盖手机'
}
})
// toRaw() 将代理对象转为一个普通对象返回
let phone2 = toRaw(phone)
console.log(phone2);
console.log('--------------------');
//定义了一份数据
// markRaw() 记一个对象为“永远不会转为响应式代理”
let food = markRaw({
name:'面包'
})
// 注意:food2就是一个普通对象
let food2 = reactive(food)
console.log(food2);
let updatePhone = ()=>{
//修改name,会触发页面更新
// phone.name += "!"
//修改type里面的属性,不会触发页面更新
phone.type.typeName += "!"
}
//自定义一个ref
function useDebouncedRef(value, delay = 200) {
let timeout
// customRef(),用于自定义一个 ref
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
},
}
})
}
let age = useDebouncedRef(20,2000)
return {
stuData,
num3,
car,
updateCar,
phone,
updatePhone,
age
}
}
}