ref

92 阅读1分钟

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的值 这是因为reftriggerRef底层都调用了triggerRefValue ,他又会调用triggerEffect 即依赖的更新