ref全家桶
vue2写法
<script>
export default{
data(){
return{
//写在这里才是响应式的
age:18
}
}
}
</script>
为什么要有ref
<template>
<div>
<button @click="changeMsg">change</button>
<div>{{message}}</div>
</div>
</template>
<script setup lang="ts">
let message:string="hello world"
const changeMsg=()=>{
message='change msg'
}
</script>
点击上面的 change 之后,script的数据message会变,视图层里的数据message不会变,说明数据不是响应式的。
ref
定义响应式数据 深层次的响应
创建:let 变量名=ref("OldValue") 修改:变量名.value=newValue 使用:{{变量名}}
一般用来定义原始类型的响应式数据
定义复杂类型数据(对象、数组)其实也是调用reactive,源码里有
<template>
<div>
<p>{{msg}}</p>
<p>{{msg2}}</p>
<button @click="changeMsg">changeMsg</button>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
//创建 let 变量名=ref("OldValue")
//基本类型
let msg=ref("ref对象")
//引用类型
let msg2=ref({name:"zs"})
const changeMsg=()=>{
//变量名.value=newValue
msg.value="change后的ref对象"
console.log(msg);
msg2.value.name="ls"//深层
console.log(msg2)
}
</script>
<style>
</style>
isRef
判断是否是一个ref对象(不常用)
格式:isRef(变量名) 返回一个boolean值:false/true
import {ref,isRef} from 'vue'
let msg=ref("ref对象")
let notRef=123
const changeMsg=()=>{
console.log(isRef(msg));//true
console.log(isRef(notRef));//false
}
shallowRef
只处理基本数据类型的响应式, 不进行对象的响应式处理。
浅层次的响应
不进行对象的响应式处理(单独使用时),视图层没有变化,后台有变化
<template>
<div>
<p>{{ message }}</p>
<button @click="changeMsg">change</button>
</div>
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
let message= shallowRef({name: "修改前"})
const changeMsg = () => {
message.value.name = '修改后'//这种格式不是响应式,无法修改视图层的数据
//message.value = { name: "ww" }//这种格式可以修改
console.log(message);
}
</script>
<style>
</style>
基本数据类型的响应式可以改变
<template>
<div>
<p>{{ msg }}</p>
<button @click="changeMsg">change</button>
</div>
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
let msg=shallowRef(111)
const changeMsg = () => {
msg.value=222
}
</script>
<style>
</style>
特殊情况
shallowRef被影响变成响应式
ref和shallowRef不能一起用,不然会影响shallowRef
<template>
<div>
<p>{{ message }}</p>
<p>{{msg}}</p>
<button @click="changeMsg">change</button>
</div>
</template>
<script setup lang="ts">
import { ref,shallowRef } from 'vue'
let msg=ref(111)
let message= shallowRef({name: "修改前"})
const changeMsg = () => {
// msg.value=2222
message.value.name = '被ref影响了'//这种格式无法修改
//message.value = { name: "ww" }//这种格式可以修改
msg.value=2222
}
</script>
<style>
</style>
源码分析
shallowRef基本数据类型和对象类型一起修改,可以修改
<template>
<div>
<p>{{ msg }}</p>
<p>{{msg1}}</p>
<button @click="changeMsg">change</button>
</div>
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
let msg=shallowRef(111)
let msg1=shallowRef({name:'dio'})
const changeMsg = () => {
msg.value=222
msg1.value.name="修改后"
}
</script>
<style>
</style>
分开也可以改,先改基本再改对象,改不了
先改对象发现改不了,先改对象再改基本可以改
<template>
<div>
<p>{{ msg }}</p>
<p>{{msg1}}</p>
<button @click="changeMsg">修改msg</button>
<button @click="changeMsg2">修改msg1对象</button>
</div>
</template>
<script setup lang="ts">
import { shallowRef } from 'vue'
let msg=shallowRef(1)
let msg1=shallowRef({name:'dio'})
const changeMsg = () => {
msg.value+=4
}
const changeMsg2 = () => {
msg1.value.name="修改后"
}
</script>
<style>
</style>
ref是否有类型限制
triggerRef
强制更新页面DOM
格式:triggerRef(变量名)
<template>
<div>
<p>{{ message }}</p>
<button @click="changeMsg">change</button>
</div>
</template>
<script setup lang="ts">
import { shallowRef, triggerRef } from 'vue'
let message= shallowRef({name: "修改前"})
const changeMsg = () => {
message.value.name = '修改后'//这种格式不是响应式,无法修改视图层的数据
triggerRef(message)//强制更新
console.log(message);
}
</script>
<style>
</style>
customRef
自定义ref
customRef 是个工厂函数要求我们返回一个对象 并且实现 get 和 set
<template>
<div>
<p>{{message}}</p>
<button @click="changeMsg">changeMsg</button>
</div>
</template>
<script setup lang="ts">
import { Ref, shallowRef, triggerRef, customRef } from 'vue'
function Myref<T>(value: T) {
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newVal: T) {
console.log('set');
value = newVal
trigger()
}
}
})
}
let message = Myref('前')
const changeMsg = () => {
message.value = '后'
console.log(message)
}
</script>
<style>
</style>
可以用来写防抖
<template>
<div>
<p>{{ message }}</p>
<button @click="changeMsg">change</button>
</div>
</template>
<script setup lang="ts">
import { Ref, shallowRef, triggerRef, customRef } from 'vue'
function Myref<T>(value: T) {
let timer:any
let count=0
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newVal: T) {
//count++
//console.log('调用了'+count+"次");
clearTimeout(timer)
timer=setTimeout(()=>{
count++
console.log('调用了'+count+"次");
value=newVal
timer=null
trigger()
},1000)
value = newVal
trigger()
}
}
})
}
let message = Myref('前')
const changeMsg = () => {
message.value = '后'
}
</script>
<style>
</style>
ref获取dom
<template>
<div>
<button @click="changeMsg">getDom</button>
<div ref="dom">I am Dom</div>
</div>
</template>
<script setup lang="ts">
import { ref,Ref, shallowRef, triggerRef, customRef } from 'vue'
const dom=ref<HTMLElement>()
const changeMsg = () => {
console.log(dom.value?.innerText)
}
</script>
<style>
</style>