vue3-ref

7/17/2020 vue3

# ref -- 做值类型的响应式, 变量命名建议xxxRef


接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。 生成值类型的响应式数据 可用于模板和reactive 通过.value修改值

无法实现响应式

<script setup lang="ts">
  let count:number = 0
  const handleClick = () => {
    count++
    console.log('count: ' + count);
  }
</script>

<template>
  <div>
    {{count}}
    <button @click="handleClick">更新</button>
  </div>
</template>

<style scoped>
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

被ref包裹后,被处理为响应式对象

<script setup lang="ts">
import { ref, Ref } from 'vue';
  let count:Ref<number> = ref(0)
  const handleClick = () => {
    count.value++
    console.log(count.value);
  }
</script>

<template>
  <div>
    {{count}}
    <button @click="handleClick">更新</button>
  </div>
</template>

<style scoped>
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

为何需要.value (实现响应式、保持响应式、传递响应式)

  • ref 是一个对象(不丢失响应式,保证响应式),value 是存储值的
  • 通过.value属性的get、set实现响应式
  • 用于模板、reactive时,不需要.value, 其他情况都需要

# 用于模板


<template>
  <div>
     <p ref="pRef">这是一段文字</p>
  </div>
</template>
 
<script setup lang="ts">
import { ref, onMounted } from 'vue';

const pRef = ref<any>(null)

onMounted(() => {
    console.log(pRef.value.innerHTML);  // 这是一段文字
})

</script>
 
<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# isref


判断是不是ref对象

<script setup lang="ts">
import { ref, Ref, isRef } from 'vue';
  let count:Ref<number> = ref(0)
  let name:string = 'xxx'
  console.log(isRef(count)); // true
  console.log(isRef(name)); // false
</script>

<template>
  <div>
   
  </div>
</template>

<style scoped>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# unref


如果参数是一个ref,则返回内布置,否则返回参数本身

val = isRef(val) ? val.value : val 的语法糖函数

<script setup lang="ts">
  import { ref, Ref, unref } from 'vue';
  function useFoo(x:number | Ref<number>){
    return unref(x)
  }
  console.log(useFoo(2));
  console.log(useFoo(ref(2)));
</script>

<template>
  <div>
   
  </div>
</template>

<style scoped>
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# shallowRef


修改.value 属性是非响应式,不会改变

注意:ref 定义的数据会触发triggerRef函数,所以如果同时使用ref和shallowRef会一起更新数据

<script setup lang="ts">
import { ref, Ref, shallowRef } from 'vue';
  let result:Ref<Object> = shallowRef({
    name: 'xxx'
  })
  const handleClick = () => {
    result.value.name = 'yyy'
    console.log(result.value);
  }
</script>

<template>
  <div>
    {{result}}
    <button @click="handleClick">更新</button>
  </div>
</template>

<style scoped>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

只跟踪.value自身变化的ref,

<script setup lang="ts">
import { ref, Ref, shallowRef } from 'vue';
  let result:Ref<Object> = shallowRef({
    name: 'xxx'
  })
  const handleClick = () => {
    result.value = {
      name : 'yyy'
    }
    console.log(result.value);
  }
</script>

<template>
  <div>
    {{result}}
    <button @click="handleClick">更新</button>
  </div>
</template>

<style scoped>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# triggerRef


与shallowRef 配合使用,解决DOM的更新

<script setup lang="ts">
import { ref, Ref, shallowRef, triggerRef } from 'vue';
  let result:Ref<Object> = shallowRef({
    name: 'xxx'
  })
  const handleClick = () => {
    result.value.name = 'yyy'
    triggerRef(result)
    console.log(result.value);
  }
</script>

<template>
  <div>
    {{result}}
    <button @click="handleClick">更新</button>
  </div>
</template>

<style scoped>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# customRef


自定义ref 响应式, customRef 是一个工厂函数,需要返回一个get\set的对象,

<script setup lang="ts">
import { customRef } from 'vue';

function MyRef<T>(value:T){
  return customRef((track, trigger) => {
    return {
      get(){
        track()
        return value
      },
      set(newVal:T){
        value = newVal
        trigger()
      }
    }
  })
}



let count = MyRef(0)

const handleClick = () => {
    count.value++
    console.log(count.value);
  }


</script>

<template>
  <div>
    {{count}}
    <button @click="handleClick">更新</button>
  </div>
</template>

<style scoped>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
更新: 8/19/2022, 2:56:36 PM