Reactive API的补充
isProxy:检查对象是否是由reactive或readonly创建的proxy.
isReactive:检查对象是否是由reactive创建的响应式代理;如果该代理是readonly建的,但包裹了由reactive 创建的另一个代理,它也会返回true ;
isReadonly:检查对象是否是由readonly 创建的只读代理。
toRaw:返回reactive或readonly 代理的原始对象(不建议保留对原始对象的持久引用。请谨慎使用)。
shallowReactive:创建一个响应式代理,它跟踪其自身property 的响应性,但不执行嵌套对象的深层响应式转换(深层还是原生对象)。
shallowReadonly:创建一个proxy,使其自身的 property为只读,但不执行嵌套对象的深度只读转换(深层还是可读、可写的)。
toRefs和toRef
toRefs:将reactive对象中所有属性都转为ref,建立连接
toRef:对其中一个属性进行转换为ref,建立连接
<script>
import { reactive, toRefs, toRef } from "vue";
export default {
setup() {
const info=reactive({name:"sk",age:18});
// toRefs:将reactive对象中所有属性都转为ref,建立连接
// let { name, age }=toRefs(info);
// toRef:对其中一个属性进行转换为ref,建立连接
let {name}=toRefs(info);
let age=toRef(info,"age");
const change=()=>{
// age.value++;
info.age++;
}
return {
name,
age,
change
}
}
}
</script>ref API的补充
unref:如果我们想要获取一个ref引用中的value,那么也可以通过unref方法︰如果参数是一个ref,则返回内部值,否则返回参数本身;这是val = isRef(val) ? val.value : val的语法糖函数;
isRef:判断值是否是一个ref对象。
shallowRef:创建一个浅层的ref对象
triggerRef:手动触发和shallowRef相关联的副作用。
<script>
import { ref, shallowRef, triggerRef } from "vue";
export default {
setup() {
// 浅层响应式
const info=shallowRef({name:"sk"});
const changeInfo=()=>{
info.value.name="james";
triggerRef(info);
}
return {
info,
changeInfo
}
}
}
</script>customRef
customRef可以是我们能够决定如何跟踪依赖与什么时候触发更新。其工厂函数需要传入track和trigger参数,并返回一个拥有get和set方法的对象:
import { customRef } from "vue";
// 自定义ref
export default function(value){
let timer=null;
return customRef((track,trigger)=>{
return {
get(){
track();
return value;
},
set(newValue){
clearTimeout(timer);
timer=setTimeout(()=>{
value=newValue;
trigger();
},1000);
}
}
})
}setup中computed的使用
计算属性需要调用computed函数来获得,computed函数支持两种传参:1.传入一个get函数;2.传入一个对象;返回值是一个ref对象:
<script>
import {ref, computed} from "vue";
export default {
setup(props) {
const firstName = ref("kobe");
const lastName = ref("bryant");
// 用法一:传入一个getter函数
// 返回值为一个ref对象computedRef
// const fullName=computed(()=>firstName.value+" "+lastName.value);
// 用法二:传入一个对象
const fullName=computed({
get:()=>firstName.value+" "+lastName.value,
set:(newValue)=>{
const names=newValue.split(" ");
firstName.value=names[0];
lastName.value=names[1];
}
})
const changeName=()=>{
// firstName.value="james";
fullName.value="shop keeper";
}
return {
fullName,
changeName
}
}
}
</script>watchEffect
基本使用
watchEffect会自动收集响应式的依赖,对于一个watchEffect中的函数,它会在一开始自动执行一次,并记录到当中用到的响应式数据,以后每当这些响应式数据发生变化时,就会再次调用这个函数:
<script>
import { ref, watchEffect} from "vue";
export default {
setup() {
// watchEffect:自动收集响应式的依赖
const name =ref("sk");
const age=ref(18);
const changeName=()=> name.value="shopkeeper";
const changeAge=()=> age.value++;
watchEffect(()=>{
console.log("name:",name.value,"age:",age.value);
})
return {
name,
age,
changeName,
changeAge
}
}
}
</script>停止侦听
watchEffect方法会返回一个方法,用于停止侦听:
<script>
import { ref, watchEffect} from "vue";
export default {
setup() {
// watchEffect:自动收集响应式的依赖
const name =ref("sk");
const age=ref(18);
const stop=watchEffect(()=>{
console.log("name:",name.value,"age:",age.value);
});
const changeName=()=> name.value="shopkeeper";
const changeAge=()=> {
age.value++;
if (age.value>25){
stop();
}
};
return {
name,
age,
changeName,
changeAge
}
}
}
</script>watchEffect清除副作用
watchEffect的入参的函数中可以有一个入参,该入参也是一个函数,用于在再次执行watchEffect函数或watchEffect被停止时调用,一般取名为onInvalidate
const stop=watchEffect((onInvalidate)=>{
const timer=setTimeout(()=>{
console.log("网络请求成功");
},2000)
// 根据name和age两个变量发送网络请求
onInvalidate(()=>{
// 在这个函数中清除额外的副作用
// request.cancel();
clearTimeout(timer);
console.log("onInvalidate");
})
console.log("name:",name.value,"age:",age.value);
});watchEffect的执行时机
watchEffect的入参的第二个参数可用于定义watchEffect的执行时机:
<script>
import { ref, watchEffect} from "vue";
export default {
setup() {
const title= ref(null);
watchEffect(()=>{
console.log(title.value);
},{
flush:"post"
});
return{
title
}
}
}
</script>flush的取值:post为先挂载在执行、pre为先执行再挂载(默认)、sync是同时进行(不推荐)。
setup中使用ref
直接在template的ref标签中使用setup的数据即可:
<template>
<div>
<h2 ref="title">哈哈哈</h2>
</div>
</template>
<script>
import { ref, watchEffect} from "vue";
export default {
setup() {
const title= ref(null);
watchEffect(()=>{
console.log(title.value);
},{
flush:"post"
});
return{
title
}
}
}
</script>watch
watch的API完全等同于组件watch选项的Property :watch需要侦听特定的数据源,并在回调函数中执行副作用;默认情况下它是惰性的,只有当被侦听的源发生变化时才会执行回调;
与watchEffect的比较,watch允许我们∶懒执行副作用(第一次不会直接执行);更具体的说明当哪些状态发生变化时,触发侦听器的执行;口访问侦听状态变化前后的值;
基本使用
watch方法的第一个参数是要监听的数据,可以是ref对象、reactive对象、数组、getter方法,第二个参数是数据改变时的回调,第三个参数时options
<script>
import { ref, reactive, watch} from "vue";
export default {
setup() {
const info =reactive({
name: "sk",
age:19
});
// 侦听watch是,传入一个getter函数
// watch(()=>info.name,(newValue,oldValue)=>{
// console.log("newValue",newValue,"oldValue",oldValue);;
// });
// 传入可响应式对象:reactive对象/ref对象
// reactive对象获取到的newValue和oldValue都是reactive对象
// watch(info,(newValue,oldValue)=>{
// console.log("newValue",newValue,"oldValue",oldValue);;
// });
// 如果希望newValue和oldValue是一个普通的对象
watch(()=>{
return {...info};
},(newValue,oldValue)=>{
console.log("newValue",newValue,"oldValue",oldValue);;
});
// ref对象获取到的newValue和oldValue都是值的本身
const name = ref("sk");
watch(name,(newValue,oldValue)=>{
console.log("newValue",newValue,"oldValue",oldValue);;
});
const changeData=()=>{
info.name="shopkeeper";
// name.value="shopkeeper";
}
return{
changeData,
info,
}
}
}
</script>watch侦听多个数据源
<script>
import { ref, reactive, watch} from "vue";
export default {
setup() {
// 定义响应式对象
const info =reactive({
name: "sk",
age:19
});
const name = ref("sk");
// 侦听多个数据源
watch([()=>{
return {...info}
},name],([newInfo,newName],[oldInfo,oldName])=>{
console.log(newInfo,newName,oldInfo,oldName);
});
const changeData=()=>{
info.name="shopkeeper";
// name.value="shopkeeper";
}
return{
changeData,
info,
}
}
}
</script>watch的选项
和options中的watch一样:
<script>
import { ref, reactive, watch} from "vue";
export default {
setup() {
// 定义响应式对象
const info =reactive({
name: "sk",
age:19,
friend:{
name:"kobe"
}
});
// 源码中,传入reactive会默认开启deep侦听,而传入getter方法不会
watch([()=>{
return {...info}
}],(newInfo,oldInfo)=>{
console.log(newInfo,oldInfo);
},{
deep:true,
immediate:true
});
const changeData=()=>{
info.friend.name="james";
}
return{
changeData,
info,
}
}
}
</script>