ref
<template>
<div>
{{m}}
</div>
<hr>
<button @click="change">修改m</button>
</template>
<script setup lang='ts'>
import { ref } from 'vue';
const m = ref({name:'jk',})
const change = () => {
m.value.name = 'bb'
console.log(m);
}
</script>
ref返回对象 要修改属性 需要value
isRef
判断是否是ref对象
console.log(isRef(m)); //true
shallowRef
ref深层次 shallowRef浅层次
<template>
<div>
ref:{{m}}
</div>
<div>
shallowRef:{{m1}}
</div>
<hr>
<button @click="change">修改shallow</button>
</template>
<script setup lang='ts'>
import { isRef, ref, shallowRef } from 'vue';
const m = ref({name:'jk',})
const m1 = shallowRef({name:'shallow'})
const change = () => {
m1.value = {
name:'change it'
} //成功修改
m1.value.name ='bb'
//修改了 但不具备响应式 响应式只到value这一层
}
</script>
ref和shallowRef不能一起使用 否则会影响ref, 造成视图的更新,这与triggerRef有关
triggerRef
<template>
<div>
ref:{{m}}
</div>
<div>
shallowRef:{{m1}}
</div>
<hr>
<button @click="change">修改shallow</button>
</template>
<script setup lang='ts'>
import { isRef, ref, shallowRef, triggerRef } from 'vue';
const m = ref({name:'jk',})
const m1 = shallowRef({name:'shallow'})
const change = () => {
m1.value.name ='bb'
//修改了 但不具备响应式 响应式只到value这一层
triggerRef(m1)
}
</script>
triggerRef 会强制更新所收集到的依赖
ref底层调用了triggerRef 所以会影响到shallowRef
customRef
相当于自定义ref 自己实现get set
例如在set中写防抖 非常好使
<template>
<hr>
<div >{{obj}}</div>
<button @click="change">改</button>
</template>
<script setup lang='ts'>
import { customRef, isRef, ref, shallowRef, triggerRef } from 'vue';
function myRef<T>(value :T) {
// 要求一个回调函数 回调函数中返回一个对象 实现set get
return customRef((track,trigger) =>{
return {
get() {
track()
return value
},
set(newValue) {
value = newValue
trigger()
},
}
})
}
const change = () =>{
obj.value = 'bc'
}
let obj = myRef<string>('只因你')
</script>
ref获取dom
与v2类似 给dom挂载ref 不同的是获取的写法不同
<template>
<div ref="dom">我测你码</div>
</template>
<script setup lang='ts'>
import { customRef, isRef, ref, shallowRef, triggerRef } from 'vue';
const dom = ref<HTMLDivElement>()
console.log(dom.value); // undefined 因为此时dom还没渲染 在函数中添加即可
</script>
<template>
<div ref="dom" @click="show">芝士雪豹</div>
</template>
<script setup lang='ts'>
import { customRef, isRef, nextTick, ref, shallowRef, triggerRef } from 'vue';
const dom = ref<HTMLDivElement>()
const show = () =>{
console.log(dom.value?.innerHTML); // 芝士雪豹
}
</script>
ref源码
ref.ts
调用createRef(value,false) 第二个参数表示是否是shallow 默认false
function createRef(value:unknown,shallow:boolean){
//判断是否是ref对象 是直接返回
if(isRef(value)) return value
//不是ref对象 则根据RefImpl类new一个
return new RefImpl(value,shallow)
}
class RefImpl<T> {
private _value:T
private _rawValue:T
constructor(value:T,isShallow:boolean){
//根据isShallow来决定 shallow是浅层 若是shallow直接返回value 因此shallowRef的响应式止步于.value 再后面就不是响应式了
this._rawValue = isShallow?value:toRaw(value)
this._value = isShallow?value:toReactive(value)
//toReactive 中判断是否为引用形式 不是直接返回即可 如果是则调用reactive
}
get(){}
set(){}
//set get与customRef类似
}
之前的坑🕳:ref和shallowRef写在一起会被影响
之前说到triggerRef可以强制更新ref的值 这是因为ref和triggerRef底层都调用了triggerRefValue ,他又会调用triggerEffect 即依赖的更新