【笔记】Vue3的响应式数据

前言

Vue3的响应式数据学习笔记
每当JS中定义的数据发生改变,HTML模板中的数据都会跟随改变

OptionsAPI

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
{{ key }}
</template>

<script>
export default {
data: function () {
return {
key: "value"
}
}
}
</script>

CompositionAPI

ref

  • 通过ref()定义基本类型的响应式数据
  • 通过unref()得到由ref()定义的响应式数据之内的原始数据
  • 通过isRef()判定数据是否是由ref()定义的响应式数据

setup函数

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
<template>
{{ key }}
</template>

<script>
import { ref, unref, isRef } from "vue"

export default {
setup: function (attrs, slots, emit) {
const key = ref("value");

// 手动解包
console.log(key.value);

// 原始数据
const unKey = unref(key);
console.log(unKey);

// 判断是否是响应式数据
console.log(isRef(key));

return {
key
}
}
}
</script>

setup语法糖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
{{ key }}
</template>

<script setup>
import { ref, unref, isRef } from "vue"

const key = ref("value");

// 手动解包
console.log(key.value);

// 原始数据
const unKey = unref(key);
console.log(unKey);

// 判断是否是响应式数据
console.log(isRef(key));
</script>

reactive

  • 通过reactive()定义对象类型的响应式数据
  • 通过isReactive()判定数据是否是由reactive()定义的响应式数据

setup函数

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
<template>
{{ key.field }}
</template>

<script>
import { reactive, isReactive } from "vue"

export default {
setup: function (attrs, slots, emit) {
const key = reactive({
field: "value"
});

// 无需手动解包
console.log(key.field);

// 判断是否是响应式数据
console.log(isReactive(key));

return {
key
}
}
}
</script>

setup语法糖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
{{ key.field }}
</template>

<script>
import { reactive, isReactive } from "vue"

const key = reactive({
field: "value"
});

// 无需手动解包
console.log(key.field);

// 判断是否是响应式数据
console.log(isReactive(key));
</script>

readonly

  • 通过readonly()包裹数据,使数据在传递给子组件后,子组件无法修改
    • readonly()可以传递非响应式数据,也可以传递由ref()reactive()定义的响应式数据
      • 如果传递的是非响应式数据,则readonly()包裹后仍然是非响应式数据
      • 如果传递的是由ref()reactive()定义的响应式数据,则readonly()包裹后仍然是响应式数据
  • 通过isReadonly()判定数据是否是由readonly()包裹的数据

setup函数

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
<template>
<Son v-bind:data="keyRef" />
<Son v-bind:data="keyReactive" />
</template>

<script>
import Son from "@/components/Son.vue";
import { ref, reactive, readonly, isReadonly } from "vue"

export default {
setup: function (attrs, slots, emit) {
const keyRef = readonly(ref("value"));
const keyReactive = readonly(reactive({
field: "value"
}));

// 仍需手动解包
console.log(keyRef.value);
// 无需手动解包
console.log(keyReactive.field);

// 判断是否是只读数据
console.log(isReadonly(keyRef));

return {
keyRef,
keyReactive
}
}
}
</script>

setup语法糖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<Son v-bind:data="keyRef" />
<Son v-bind:data="keyReactive" />
</template>

<script>
import Son from "@/components/Son.vue";
import { ref, reactive, readonly, isReadonly } from "vue"

const keyRef = readonly(ref("value"));
const keyReactive = readonly(reactive({
field: "value"
}));

// 仍需手动解包
console.log(keyRef.value);
// 无需手动解包
console.log(keyReactive.field);

// 判断是否是只读数据
console.log(isReadonly(keyRef));
</script>

toRaw

  • 通过toRaw()得到原始数据

setup函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
import { ref, reactive, toRaw } from "vue"

export default {
setup: function (attrs, slots, emit) {
const keyRef = ref("value");
const keyReactive = reactive({
field: "value"
});

// 得到原始数据
console.log(toRaw(keyRef));
console.log(toRaw(keyReactive));
}
}
</script>

setup语法糖

1
2
3
4
5
6
7
8
9
10
11
12
<script setup>
import { ref, reactive, toRaw } from "vue"

const keyRef = ref("value");
const keyReactive = reactive({
field: "value"
});

// 得到原始数据
console.log(toRaw(keyRef));
console.log(toRaw(keyReactive));
</script>

Ref的用法

定义响应式数据

传送门

获取DOM元素

setup函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div ref="div"></div>
</template>

<script>
import { ref, onMounted } from "vue"

export default {
setup: function () {
let divElement = ref(null);

onMounted(() => {
console.log(divElement.value);
});
}
}
</script>

setup语法糖

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div ref="div"></div>
</template>

<script setup>
import { ref, onMounted } from "vue"

let divElement = ref(null);

onMounted(() => {
console.log(divElement.value);
});
</script>

获取子组件

setup函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<Son ref="son" />
</template>

<script>
import Son from "@/components/Son.vue"
import { ref, onMounted } from "vue"

export default {
setup: function () {
let sonComponent = ref(null);

onMounted(() => {
console.log(sonComponent.value);
});
}
}
</script>

setup语法糖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<Son ref="son" />
</template>

<script setup>
import Son from "@/components/Son.vue"
import { ref, onMounted } from "vue"

let sonComponent = ref(null);

onMounted(() => {
console.log(sonComponent.value);
});
</script>

完成