vue3中很多实现响应式的方式,我们比较常用的有一些ref reactive等操作,但是其实文档本身是帮我们实现了不止这些,他有帮我们考虑了很多种不同的业务场景,今天就简单的介绍一下
<!--
* @Description: 测试ref unref isRef toRef toRefs shallowRef triggerRef customRef
* @author:clearlove
* @createTime: 2023-12-11 14:02:55
-->
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 count {{count}}
</div>
</template>
<script setup>
import {ref} from 'vue'
const count = ref(0)
const addCount = ()=>{
count.value++
}
</script>
他本身是一个语法糖:val = isRef(val) ? val.value : val;
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 count {{unRefCount}}
</div>
</template>
<script setup>
import {ref,unref} from 'vue'
const count = ref(0)
const unRefCount = unref(count)
const addCount = ()=>{
count.value++
console.log(count.value,unRefCount)
}
</script>
import {ref,unref,isRef} from 'vue'
const count = ref(0)
const unRefCount = unref(count)
const ordinaryCount = 0
console.log(isRef(count),isRef(unRefCount),isRef(ordinaryCount)) // true false false
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 count {{countObject.num}}
</div>
</template>
<script setup>
import {reactive} from 'vue'
const countObject = reactive({
num : 0
})
const addCount = ()=>{
countObject.num++
}
</script>
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 count {{toRefCount}}
<hr />
原对象的 num {{count.num}}
</div>
</template>
<script setup>
import { toRef, ref } from 'vue'
const count = ref({
num: 0
})
const toRefCount = toRef(count.value, 'num')
/**
toRef可以改变一个原对象中的某一个属性,toRef 接受两个参数,第一个是对象,第二个是属性值,
这个属性值就和当前的定义的变量保持同步,当然这里使用 reactive 也是可以的
*/
const addCount = () => {
// 以下两个值,任意改变都会印象另一个对应的属性
count.value.num++
// toRefCount.value++
}
</script>
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 count {{toRefCount.num}}
<hr />
原对象的 num {{count.num}}
</div>
</template>
<script setup>
import { toRefs, reactive } from 'vue'
const count = reactive({
num: 0,
age: 0
})
const toRefCount = toRefs(count)
/**
* toRefs 之后会将count 转为普通对象,toRefCount 具备了 count 对象的属性,
且里面的属性均为 ref 响应式对象
toRefCount 的 num / age 和 count
里面的 num / age 保持同步
不管改哪里的数据,两边均保持同步
*/
const addCount = () => {
count.num++
// toRefCount.num.value++
}
</script>
toRefs应用
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 num {{num}}
<hr />
原对象的 num {{count.num}}
</div>
</template>
<script setup>
import { reactive,toRefs } from 'vue'
const count = reactive({
num: 0,
age: 0
})
// const { num, age } = count // 这里解构之后 num 和 age 均失去了响应式
const toRefCount = toRefs(count)
const { num } = toRefCount // 这里解构之后 均还存在 ref 的响应式,因为 toRefs 之后给内部的属性均添加了响应式
const addCount = () => {
count.num++
}
</script>
// 当然这里有点冗余了,你可以直接使用对象[key]的方式进行获取数据,也是可以保留响应式进行展示的
<template>
<div>
<el-button @click="addCount">count++</el-button>
<el-button @click="addCountValue">改变 value</el-button>
</div>
<br />
<div>
当前 num {{count.num}}
</div>
</template>
<script setup>
import { shallowRef } from 'vue'
/**
shallowRef 仅仅对当前的 value 改变可以进行监听响应式,深层的是不具备响应式的
*/
const count = shallowRef({
num: 0,
})
// 这里无法实现动态的 num
const addCount = () => {
count.value.num++
}
// 这里可以改变动态 num
const addCountValue = ()=>{
let temp = count.value.num
temp++
count.value = {
num : temp
}
}
</script>
<template>
<div>
<el-button @click="addCount">count++</el-button>
<el-button @click="addCountValue">改变 value</el-button>
</div>
<br />
<div>
当前 num {{count.num}}
</div>
</template>
<script setup>
import { shallowRef,triggerRef } from 'vue'
/**
triggerRef 可以对shallowRef 浅层不具备更新的属性进行强制更新
*/
const count = shallowRef({
num: 0,
})
// 这里添加shallowRef 之后可以实现动态的 num
const addCount = () => {
count.value.num++
triggerRef(count)
}
</script>
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 num {{num}}
</div>
</template>
<script setup>
import { customRef } from 'vue'
/**
customRef 可以自定义一个 ref 的功能函数, 它可以实现的自定义一个条件判断进行区分哪里是需要进行响应式的
*/
const diyRef = ((value) => {
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
setTimeout(()=>{
value = newValue
trigger()
},2000)
}
}
})
})
const num = diyRef(0)
const addCount = () => {
num.value++
}
</script>
<template>
<div>
<el-button @click="addCount">count++</el-button>
</div>
<br />
<div>
当前 num {{obj.age}} - {{obj.grade.english}}
</div>
</template>
<script setup>
import { shallowReactive } from 'vue'
/**
shallowReactive 只有根节点是响应式的,内部深层的是不具备响应式的
*/
const obj = shallowReactive({
age: 0,
grade: {
english: 90
}
})
const addCount = () => {
// 这里有个很奇怪的点 如果两个同时写上的话,两个都是具备响应式的 如果只有obj.grade.english++ 是不具备的 不晓得是不是一个 bug 按照官方的解释,这里是不会进行响应式进行页面更新的
obj.grade.english++
obj.age++
}
</script>
这篇文章也许不会帮你全完全了解这些概念,但是学习的过程就是你要先知道,然后再追求精通,所以我的目的是希望通过这篇文章可以对这些概念有一个简单的认识,具体他是做什么的,哪里可以用到,要看你们实际业务场景是不是需要对应的一些概念,喜欢的可以收藏一下,拜拜