随笔 - 12  文章 - 0  评论 - 0  阅读 - 6086

Vue3系列4--ref和reactive响应式

1 ref

接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
  <div>
    <button @click="changeMsg">change</button>
    <div>{{ message }}</div>
  </div>
</template>
  
<script setup lang="ts">
let message: string = "我是message"
  
const changeMsg = () => {
   message = "change msg"
}
</script>
  
<style>
</style>

我们这样操作是无法改变message  的值 应为message 不是响应式的无法被vue 跟踪要改成ref。响应式就是在页面上实时显示修改的值。

Ref TS对应的接口:

1
2
3
interface Ref<T> {
  value: T
} // 对于接口问题,是TS语法,如果不清楚,直接看TS

但是被ref包裹后需要使用value来进行赋值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
  <div>
    <button @click="changeMsg">change</button>
    <div>{{ message }}</div>
  </div>
</template>
  
<script setup lang="ts">
import {ref,Ref} from 'vue'
let message:Ref<string> = ref("我是message")let message= ref<string>("我是message"// 第二种方式const changeMsg = () => {
   message.value = "change msg"
}
</script>
  
<style>
</style>

2 isref

判断是不是一个ref对象
1
2
3
4
5
6
7
8
import { ref, Ref,isRef } from 'vue'
let message: Ref<string | number> = ref("我是message")
let notRef:number = 123
const changeMsg = () => {
  message.value = "change msg"
  console.log(isRef(message)); //true
  console.log(isRef(notRef)); //false
}

3 shallowref

创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的

例子1 

修改其属性是非响应式的这样是不会改变的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
  <div>
    <button @click="changeMsg">change</button>
    <div>{{ message }}</div>
  </div>
</template>
  
<script setup lang="ts">
import { Ref, shallowRef } from 'vue'
type Obj = {
  name: string
}
let message: Ref<Obj> = shallowRef({
  name: "唐少"
})
  
const changeMsg = () => {
  message.value.name = '唐少2'
}
</script>
  
<style>
</style>

例子2

这样是可以被监听到的修改value,必须要修改整个对象才行

1
2
3
4
5
6
7
8
9
10
11
import { Ref, shallowRef } from 'vue'
type Obj = {
  name: string
}
let message: Ref<Obj> = shallowRef({
  name: "唐少"
})
  
const changeMsg = () => {
  message.value = { name: "唐少2" }
}

4 triggerRef 

为了解决shallowRef的问题,我们强制更新页面DOM,这样也是可以改变值的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
  <div>
    <button @click="changeMsg">change</button>
    <div>{{ message }}</div>
  </div>
</template>
  
<script setup lang="ts">
import { Ref, shallowRef,triggerRef } from 'vue'
type Obj = {
  name: string
}
let message: Ref<Obj> = shallowRef({
  name: "唐少"
})
  
const changeMsg = () => {
  message.value.name = '唐2'
 triggerRef(message)
}
</script>
  
<style>
</style>

5 customRef

自定义ref ,customRef 是个工厂函数要求我们返回一个对象 并且实现 get 和 set

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
<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 = '唐少2'
  // triggerRef(message)
}
</script>

6 reactive

用来绑定复杂的数据类型 例如 对象 数组

reactive 源码约束了我们的类型,类型必须是object,不能绑定普通的类型,会报错。你如果用ref去绑定对象 或者数组等复杂的数据类型 我们看源码里面其实也是 去调用reactive,但使用reactive 去修改值无须.value

  • reactive 基础用法
1
2
3
4
5
import { reactive } from 'vue'
let person = reactive({
   name:"唐少"
})
person.name = "唐少2"
  • 数组异步赋值问题
1
2
3
4
5
6
// 这样赋值页面是不会变化的因为会脱离响应式<br>let person = reactive<number[]>([])
setTimeout(() => {
  person = [1, 2, 3]
  console.log(person);
   
},1000)
  • 解决方案1:push
1
2
3
4
5
6
7
8
import { reactive } from 'vue'
let person = reactive<number[]>([])
setTimeout(() => {
  const arr = [1, 2, 3]
  person.push(...arr)
  console.log(person);
   
},1000)
  • 解决方案2:包裹一层对象
1
2
3
4
5
6
7
8
9
10
11
12
type Person = {
  list?:Array<number>
}
let person = reactive<Person>({
   list:[]
})
setTimeout(() => {
  const arr = [1, 2, 3]
  person.list = arr;
  console.log(person);
   
},1000)

7 readonly

拷贝一份proxy对象将其设置为只读

1
2
3
4
5
import { reactive ,readonly} from 'vue'
const person = reactive({count:1})
const copy = readonly(person)
 //person.count++
 copy.count++

8 shallowReactive 

只能对浅层的数据 如果是深层的数据只会改变值 不会改变视图

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
<template>
  <div>
    <div>{{ state }}</div>
    <button @click="change1">test1</button>
    <button @click="change2">test2</button>
  </div>
</template>
  
<script setup lang="ts">
import { shallowReactive } from 'vue'
  
const obj = {
  a: 1,
  first: {
    b: 2,
    second: {
      c: 3
    }
  }
}
  
const state = shallowReactive(obj)
function change1() {
  state.a = 7
}
function change2() {
  state.first.b = 8
  state.first.second.c = 9
  console.log(state);
}
  
</script>
  
  
<style>
</style> 

9  toRef

如果原始对象是非响应式的就不会更新视图 数据是会变的,如果原始对象是响应式的是会更新视图并且改变数据的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
   <div>
      <button @click="change">按钮</button>
      {{state}}
   </div>
</template>
  
<script setup lang="ts">
import { reactive, toRef } from 'vue'
  
const obj = {
   foo: 1,
   bar: 1
}
  
const state = toRef(obj, 'bar')
// bar 转化为响应式对象
  
const change = () => {
   state.value++
   console.log(obj, state);
}
</script>

10  toRefs

可以帮我们批量创建ref对象主要是方便我们解构使用

1
2
3
4
5
6
7
8
9
10
import { reactive, toRefs } from 'vue'
const obj = reactive({
   foo: 1,
   bar: 1
})
  
let { foo, bar } = toRefs(obj)
  
foo.value++
console.log(foo, bar);

11  toRaw

将响应式对象转化为普通对象

1
2
3
4
5
6
7
8
9
10
11
12
13
import { reactive, toRaw } from 'vue'
  
const obj = reactive({
   foo: 1,
   bar: 1
})
  
const state = toRaw(obj)
// 响应式对象转化为普通对象
  
const change = () => {
   console.log(obj, state);
}

 

posted on   LotusFlower  阅读(310)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
< 2025年2月 >
26 27 28 29 30 31 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 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示