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. toRef和toRefs
toRef()方法,用于将一个reactive对象里面的指定属性以ref形式的对象返回
这样写的好处是,可以简化模板里面的语法。
name:toRef(student,'name'),
age:toRef(student,'age'),
sex:toRef(student,'sex'),
address:toRef(student,'address')
`
toRefs()方法,用于将一个reactive对象返回一个新对象,
该对象里面的所有属性都是一个ref对象。
<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)
}
}
}
3. 其他的组合式API
readonly()函数,返回一份只读数据,这个只读是“深层的”,内部任何嵌套的属性也都是只读的
注意:该方法,不能将一个普通值类型数据转为只读数据
isRef()检查值是否为一个 ref 对象。
customRef()创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 track 和 trigger 函数作为参数,并且应该返回一个带有 get 和 set 的对象.
shallowRef()创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的。
triggerRef()手动执行与 shallowRef
关联的任何作用 (effect)。
<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
}
}
}