请注意,store 是一个用reactive 包裹的对象,这意味着不需要在getter 之后写.value,但是,就像setup 中的props 一样,我们不能对其进行解构

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
40
<!--
* @Description:
* @Author: xiuji
* @Date: 2022-11-20 09:14:30
* @LastEditTime: 2023-04-14 15:44:58
* @LastEditors: Do not edit
-->
<template>
<div class="content">
<h2>
<!-- {{ store.bikini }}--{{ store.count }} -->
{{ count }}
</h2>
<button @click="addCount">addCount</button>
</div>
</template>

<script setup lang="ts">
import { useStore } from '@/store/index.ts';
const store = useStore();
// ❌ 这不起作用,因为它会破坏响应式
// 这和从 props 解构是一样的
let { count } = store;
// 此时count已经不是响应式的了
const addCount = () => {
count++;
console.log('count', count);
};
</script>

<style lang="scss" scoped>
.content {
position: relative;
flex: 1;
height: 100%;
margin: 20px;
border: 1px solid #ccc;
overflow: auto;
}
</style>

为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()。 它将为任何响应式属性创建 refs。详情参见Pinia官方文档

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
<!--
* @Description:
* @Author: xiuji
* @Date: 2022-11-20 09:14:30
* @LastEditTime: 2023-04-14 15:43:45
* @LastEditors: Do not edit
-->
<template>
<div class="content">
<h2>
<!-- {{ store.bikini }}--{{ store.count }} -->
{{ count }}
</h2>
<button @click="addCount">addCount</button>
</div>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useStore } from '@/store/index.ts';
const store = useStore();
// `count`是响应式引用
const { count } = storeToRefs(store);
const addCount = () => {
console.log('count', count);
count.value++
};
</script>

<style lang="scss" scoped>
.content {
position: relative;
flex: 1;
height: 100%;
margin: 20px;
border: 1px solid #ccc;
overflow: auto;
}
</style>

storeToRefs其原理跟toRefs 一样的给里面的数据包裹一层toRef

通过toRaw使store变回原始数据防止重复代理

循环store 通过 isRef isReactive 判断 如果是响应式对象直接拷贝一份给refs 对象 将其原始对象包裹toRef 使其变为响应式对象