reactive判断的API
- isProxy:检查对象是否由reactive或readonly创建的proxy
- isReactive: 判断是否由reactive创建的响应式原理
- isReadonly
- toRaw:返回reactive代理的原始对象
- shallowReactive:创建一个响应式代理,跟踪自身property的响应性,但不执行嵌套对象的深层响应式转换
shallowReadonly:创建一个proxy,使其自身的property为只读,但不执行嵌套对象的深度只读转换 从vue中导入 import .. from 'vue'
toRef和toRefs的使用
如果想要结构出来reactive处理的对象,这些属性结构出来不具有响应式.可以使用toRefs,可以将reactive对象属性都转成ref
javascript
export default {
setup() {
const info = reactive({name: 'juju', age: 18});
let { name, age } = info;
const btnClick = () => {
// info.age++
age++
console.log(age)
}
return {
info,
btnClick
}
}
}
这时就可以使用toRef,这样使得结构出来的属性具有响应式,且修改其中属性,reactive代理对象的属性也会改变
javascript
<template>
<div>
<button @click="btnClick">年龄增加</button>
{{ name }} - {{ age }}
</div>
</template>
import { reactive, toRefs } from 'vue';
export default {
setup() {
const info = reactive({name: 'juju', age: 18});
let { name, age } = toRefs(info);
console.log(age)
const btnClick = () => {
// info.age++
age.value++
console.log(age.value) //此时age是一个ref对象,因此要使用age.value++
}
return {
name,
age,
btnClick
}
}
}
toRef对其中一个属性转成ref
ini
let age = toRef(info, "age");
ref其他API
- unref,获取ref中的value
- isRef:判断是否是一个ref对象
- shallowRef:创建一个浅层的ref对象
- triggerRef:手动触发和shollowRef相关联的副作用
ini
const info = shallowRef({name: 'juju'})
//只有info.value = {name: 'kobe'}时才是响应式,info.value.name不会改变
computed
xml
<template>
<div>
{{ fullName }}
<button @click="btnClick">改变名字</button>
</div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
setup() {
const firstName = ref("kobe");
const lastName = ref("Bryant");
// 用法一传入一个getter函数
const fullName = computed(() => firstName.value + " " + lastName.value);
// 用法二传入一个对象,包括getter和setter.computed返回值是一个ref对象
const fullName = computed({
get: () => firstName.value + " " + lastName.value,
set(newVal) {
const names = newVal.split(" ");
firstName.value = names[0];
lastName.value = names[1];
}
})
const btnClick = () => {
lastName.value = "james"
//用法二
fullName.value = "juju L"
}
return {
firstName,
lastName,
fullName,
btnClick
}
}
}
</script>
侦听数据的变化watch
在前面的OPtionAPI中,我们可以通过watch选项来侦听data或者props数据变化。在compositionAPI,我们可以使用watchEffect和watch来完成响应式数据的侦听。
- watchEffect用于自动收集响应式数据的依赖,默认会执行一次
- watch需要手动指定侦听的数据源。
ini
const name = ref("juju");
const age = ref(18);
const changeName = () => {
name.value = "harden"
}
const changeAge = () => {
age.value++;
}
// 默认执行一次,看看用到哪些ref对象,用到的自动进行监听
watchEffect(() => {
console.log("name:",name.value)
})
watchEffect停止侦听
watchEffect返回一个函数,执行这个函数,停止侦听
scss
const stop = watchEffect(() => {
console.log("name:",name.value,"age:",age.value)
})
const changeAge = () => {
age.value++;
if(age.value > 25) {
stop();
}
}
watchEffect清除副作用
当我们给watchEffect传入的函数被回调时,可以获取一个参数: onInvalidata,当副作用即将重新执行或者侦听器被停止时会执行该函数传入的回调函数
javascript
const stop = watchEffect((onInvalidate) => {
onInvalidate(()=> {
// 在这个函数中清楚额外的副作用
// request.cancel
})
console.log("name:",name.value,"age:",age.value)
})
在setup中获取到元素ref
javascript
<template>
<div>
<h2 ref="title">哈哈哈哈哈哈</h2>
</div>
</template>
const title = ref(null);
return {
title
}
此时可以在挂载完成之后获得ref为title的值
watchEffect执行时机
默认情况下,watchEffect会立即执行。如果想要在某种情况发生之后执行,需要传入第二个参数
javascript
const stop = watchEffect((onInvalidate) => {
onInvalidate(()=> {
// 在这个函数中清楚额外的副作用
// request.cancel
})
console.log(title.value)
},{
flush: "post" //挂载完成之后执行,pre是立即执行
})
watch侦听器的参数类型
watch侦听特定的数据源,只有当侦听的源发生变化才会执行回调 与watchEffect比较,watch运行我们
- 第一次不会直接执行
- 更具体说明哪些状态发生变化,触发侦听器
- 访问侦听变化前后的值
watch侦听函数有两种类型: 一个getter函数,但是该getter函数必须引用可响应式对象(比如reactive或ref) 直接写入一个可响应式对象,ref(如果是一个reactive对象侦听,需要进行某种转换)
第一种用法,侦听watch传入getter函数
xml
<template>
<div>
{{ info.name }}
<button @click="btnClick">改变</button>
</div>
</template>
<script>
import { ref, reactive, computed, watchEffect,watch } from 'vue'
export default {
setup() {
const info = reactive({name: 'juju', age: 18});
watch(() => info.name, (newVal, oldVal) => {
console.log("newVal:", newVal,"oldVal:", oldVal)
})
const btnClick = () => {
info.name = 'harden'
}
return {
info,
btnClick
}
}
}
</script>
<style scoped>
</style>
第二种用法,侦听watch传入reactive对象
javascript
const info = reactive({name: 'juju', age: 18});
// 获取到的oldval和oldval都是reactive对象
watch(info, (newVal, oldVal) => {
console.log("newVal:", newVal,"oldVal:", oldVal)
})
如果希望newval和oldval是普通对象,可以结构reactive对象
javascript
watch(() => {
return {...info}
}, (newVal, oldVal) => {
console.log("newVal:", newVal,"oldVal:", oldVal)
})
第三种,传入ref对象
javascript
const name = ref("why")
watch(name, (newVal, oldVal) => {
console.log("newVal:", newVal,"oldVal:", oldVal)
})
const btnClick = () => {
name.value = 'harden'
}
侦听多个数据源
javascript
watch([info,name], (newVal,oldVal) => {
console.log("newVal:", newVal,"oldVal:", oldVal)
})
获取新旧值可以进行结构
css
watch([info,name], ([newInfo, newName],[oldInfo,oldName]) => {
console.log(newInfo, newName,oldInfo, oldName)
})
深度监听
默认对reactive对象深度监听
javascript
watch(() => {
return {...info}
}, (newVal,oldVal) => {
console.log(newVal, oldVal)
},{
deep: true,
immediate: true
})