代码
- store
import { defineStore } from "pinia";
import { ref } from "vue";
export const useMyTestStore = defineStore('mytestStore', () => {
// state
const count = ref(0);
const count2 = ref(1);
const increment2 = () => {
count2.value++;
};
const increment = () => {
count.value++;
};
return {
count,
count2,
increment,
increment2
};
});
- 使用方式1,直接解构,结果是不能响应式
<template>
<div>
<h1>Count: {{ count }}</h1>
<button @click="increment">Increment</button>
<div>
{{ count2 }}
</div>
</div>
</template>
<script setup>
import { ref, reactive, computed, onMounted, nextTick } from 'vue';
import { useMyTestStore } from './store/mytestStore';
const { count, increment } = useMyTestStore();
// 打印出来不是一个ref对象,会失去响应式,打印出来直接是值
console.log(count, "slkfjsdlfjsldfjsd")
const count2 = computed(() => {
return count
})
console.log(count2.value, "sdfsdfsdfsfcvxcsfsdf")
// 打印出来是一个proxy对象
console.log(useMyTestStore(), "slfjsldfjslfjsldfjsljnvsld")
</script>
- 正确使用的几种方式可以store 响应式
<template>
<div>
<h1>Count: {{ count }}</h1>
<button @click="increment">Increment</button>
</div>
<div>
<h1>Count2: {{ count2 }}</h1>
<button @click="increment2">Increment</button>
</div>
<div>
count3: {{ count3 }}
</div>
<div>
<!-- 直接读取store的变量也可以响应式 -->
count4: {{ store.count2 }}
</div>
</template>
<script setup>
import { ref, reactive, computed, onMounted, nextTick } from 'vue';
import { storeToRefs } from "pinia"
import { useMyTestStore } from './store/mytestStore';
const store = useMyTestStore();
// 加上storeToRefs解构store的数据才不会失去响应式
const { count, count2 } = storeToRefs(store);
// 方法需要直接解构
const { increment, increment2 } = store;
console.log(count, "count")
// computed 读取store的自变量也可以响应式
const count3 = computed(() => store.count2)
</script>
总结
这篇文章讨论了在 Vue 3 中使用 Pinia 时,解构赋值导致响应性丢失的问题,并提供了解决方案。以下是文章的主要内容总结:
问题描述
在使用 Pinia 作为状态管理库时,通过解构赋值获取 store 中的状态可能会导致这些状态失去响应性。这是因为解构赋值会创建原始数据的浅拷贝,而这些拷贝并不是响应式的。
解决方案
-
使用
storeToRefs
:- 通过
storeToRefs
函数将 Pinia store 中的状态转换为响应式引用。即使通过解构赋值获取状态,这些状态仍然保持响应性。
import { defineComponent } from 'vue'; import { useStore } from './stores/yourStore'; import { storeToRefs } from 'pinia'; export default defineComponent({ setup() { const store = useStore(); const { someState, anotherState } = storeToRefs(store); return { someState, anotherState, }; }, });
- 通过
-
使用
computed
或watch
:- 如果需要基于 store 中的状态计算新值或监听这些状态的变化,可以使用 Vue 的
computed
或watch
。这虽然不是直接解决解构赋值响应性丢失的问题,但提供了另一种处理响应性数据的方法。
import { defineComponent, computed } from 'vue'; import { useStore } from './stores/yourStore'; export default defineComponent({ setup() { const store = useStore(); const computedValue = computed(() => store.someState + 1); return { computedValue, }; }, });
- 如果需要基于 store 中的状态计算新值或监听这些状态的变化,可以使用 Vue 的
-
直接访问 Store 属性:
- 如果不涉及解构赋值,直接在模板或计算属性中访问 store 的属性,这些属性自然是响应式的。
<template> <div>{{ store.someState }}</div> </template> <script> import { defineComponent } from 'vue'; import { useStore } from './stores/yourStore'; export default defineComponent({ setup() { const store = useStore(); return { store }; }, }); </script>