携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
一、Reactive API
reactive API对传入的类型是有限制的,它要求我们必须传入的是一个对象或者数组类型:
1、Reactive判断api isProxy:判断对象是否由reactive或者readonly创建的对象。
//判断reactive
const info = reactive({ name: "zhs", age: 23 });
console.log(isProxy(info)) //true
//判断readonly
const info = readonly({ name: "zhs", age: 20 });
console.log(isProxy(info)) //true
1234567
isReactive:检查对象是否是reactive创建的响应式代理,如果该代理是 readonly 建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true
const info = reactive({ name: "zhs", age: 23 });
console.log(isReactive(info)) //true
//即使在readonly外层包裹reactive也是可以的。
const info = reactive({ name: "zhs", age: 23 });
console.log(isReactive(info)) //true
//其代理为readonly创建的,但是其内部为reactive创建的,打印结果为true,反之为false.
const info = reactive({name:"zs"})
const set = readonly(info)
console.log(isReactive(set)) //true
isReadonly:检查对象是否由readonly创建的只读代理
const info = readonly({name:"zhs"})
console.log(isReadonly(info)) //true
12
toRaw:返回reactive和readonly代理的原始对象(不建议保留对原始对象的持久引用。请谨慎使用)
const info = readonly({name:"zhs"})
console.log(toRaw(info)) // {name:"zs"}
12
shallowReactive:创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (深层还是原生对象)
let info = shallowReactive({ info: { counter: 1 }, age: 20 });
当我们改变age的值时,页面会进行重新渲染,当我们改变counter的值时,不会进行页面的重新渲染。
12
shallowReadonly:创建一个 proxy,只进行对象浅层次的只读设置,使其自身的 property 为只读,深层次仍然是原生对象,(深层还是可读、可写的)。
const info = shallowReadonly(
{
baseInfo: { name: "zhs", age: 23 },
scores: 100,
});
如上面代码所示,此时改变scores的值会报出warning,当改变baseInfo中的age值时,页面不会
发生更新,因为此时baseInfo中的对象是普通对象,而不是响应式对象。
二、ref相关api
在setup中如何使用ref或者元素或者组件?
要定义一个ref对象,绑定到元素或者组件的ref属性上即可:
<template>
<div>
<h2 ref="h2Ref" />
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup(){
const h2Ref = ref(null)
return {
h2Ref
}
}
}
</script>
如果我们使用ES6的解构语法,对reactive返回的对象进行解构获取值,那么之后无论是修改结构后的变量,还是修改reactive
返回的state对象,数据都不再是响应式的:可以使用toRefs:可以将reactive返回的对象中的属性都转成ref;
toRefs
let info = reactive({ name: "zhs", age: 23 });
return {
...info
}
1234
此时我们使用reactive来设置响应式对象时,此时返回的解构对象不是响应式的,我们可以使用toRefs来解决。
let info = reactive({name:"zhs", age:23})
return {
...toRefs(info)
}
此时就相当于对info解构后的内容进行设置ref响应式
import { reactive, toRef } from "vue";
export default {
setup() {
const info = reactive({ name: "zhs", age: 23 });
let age = toRef(info, "age")
//toRef第一个参数是reactive对象,第二个参数是属性
//表示从该响应式对象中取出age属性并将其转化为ref对象
let {name} = info
const changeAge = () => {
age.value++ //age为ref对象
};
const changeName = () => {
name= "dddd"; //这里不加value,因为其不是ref对象
};
return {
age,
name,
changeName,
changeAge,
};
},
};
2. ref的其他api
unref:将取出ref中的value值,如果参数是一个 ref,则返回内部值,否则返回参数本身;
const age = ref(20)
console.log(age.value) //20
console.log(unref(age)) //20
//其内部可以表示为:
//这是 val = isRef(val) ? val.value : val 的语法糖函数;
isRef:判断一个对象是否是一个ref对象
const age = ref(20)
console.log(isRef(age)) //true
shallowRef:创建浅层的ref对象
import { ref } from 'vue'
export default {
setup() {
const info = ref({name:"sx", age:2})
const changeAge = () => {
info.value.age++
}
return {
info,
changeAge
}
}
}
此时当改变age中的值时,会发生页面的改变。
import { ref, shallowRef } from 'vue'
export default {
setup() {
const info = shallowRef({name:"sx", age:2})
const changeAge = () => {
info.value.age++
console.log(info.value)
}
return {
info,
changeAge
}
}
}
此时当改变age的值时,不会发生页面的改变。
triggerRef: 手动触发和shallowRef相关联的副作用。
import { ref, shallowRef, triggerRef } from 'vue'
export default {
setup() {
const info = shallowRef({name:"sx", age:2})
const changeAge = () => {
info.value.age++
console.log(info.value)
triggerRef(info) //加上triggerRef就能改变页面中的内容
}
return {
info,
changeAge
}
}
}
customRef: 创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制
- 它需要一个工厂函数,该函数接受 track 和 trigger 函数作为参数;
- 并且应该返回一个带有 get 和 set 的对象;
- 一般来说,
track()应该在get()方法中调用,而trigger()应该在set()中调用。然而事实上,你对何时调用、是否应该调用他们有完全的控制权。
案例:双向绑定的属性进行防抖 ref 的操作,即只在最近一次 set 调用后的一段固定间隔后再调用:
import { customRef } from "vue"
export function useDebouncedRef(value, delay = 200) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
在组件中使用
<script setup>
import { useDebouncedRef } from './debouncedRef'
const text = useDebouncedRef('hello')
</script>
<template>
<input v-model="text" />
</template>