Vue3中能否用watch监听原始值?加载组件不响应问题求助
问题
每次获取数据时,希望通过修改布尔值来渲染<Loading />组件,不想依赖数组长度作为判断条件,但<Loading />组件始终不响应state.isLoading的变化。尝试用watch测试this.isLoading是否变化,但watch从未输出日志。想咨询:Vue3中能否用watch监听原始值?若不可行,有没有类似React useEffect的替代方案?
相关代码
App.vue
<script setup> import { RouterView } from 'vue-router' import { watch, ref, onMounted, reactive } from 'vue'; import Navbar from './components/Navbar.vue' import { useShopStore } from './stores/shopStore'; const shop = useShopStore() const bool = ref(shop.isLoading) console.log(bool) watch(bool.value, (newBool) => { console.log(newBool) }, { deep: true }) </script>
Category.vue
<template> <LoadingVue v-if="shop.isLoading" /> <div v-else class="category__menu"> <CardVue v-for="item in shop.category" :item="item" :key="item.id" /> </div> </template>
ShopStore.js
actions: { async getProducts(path) { if (typeof path !== 'string' || path === undefined) return this.setLoading() try { const response = fetch(`https://fakestoreapi.com/products/category/${path}`) .then(res => res.json()) .then(res => this.category = res) } catch (error) { console.log(error) alert('Something went wrong') } this.setLoading() }, setLoading() { console.log('setLoading') this.isLoading = !this.isLoading } }
解答
1. Vue3可以监听原始值,但你的写法有误
你当前用watch(bool.value, ...)直接监听的是一个原始布尔值,这个值只是shop.isLoading的初始快照,和store中的响应式状态没有关联——当store里的isLoading变化时,bool.value不会自动同步更新,所以watch自然不会触发日志。
正确的监听方式有两种:
- 直接监听store中的响应式状态(前提是
isLoading在store里用ref/reactive定义):
watch(() => shop.isLoading, (newVal) => { console.log(newVal) })
- 如果要通过
bool中转,用计算属性同步响应式状态:
import { computed } from 'vue' const bool = computed(() => shop.isLoading) watch(bool, (newVal) => console.log(newVal))
2. Loading组件不响应的核心问题:异步逻辑顺序错误
你的getProducts标注了async,但内部用.then处理请求却没有加await,导致两次setLoading几乎同时执行:第一次打开loading后,请求还没完成,第二次关闭loading的代码就已经执行,最终isLoading相当于没有变化,视图自然不会更新。
修复后的异步逻辑:
async getProducts(path) { if (typeof path !== 'string' || path === undefined) return this.setLoading() try { const res = await fetch(`https://fakestoreapi.com/products/category/${path}`) const data = await res.json() this.category = data } catch (error) { console.log(error) alert('Something went wrong') } finally { // 用finally确保请求成功/失败都能关闭loading this.setLoading() } }
3. 类似React useEffect的替代方案:watchEffect
Vue3的watchEffect和React useEffect逻辑一致,它会自动追踪回调中用到的响应式依赖,当依赖变化时自动执行回调,无需手动指定监听目标:
import { watchEffect } from 'vue' watchEffect(() => { // 自动监听shop.isLoading的变化 console.log(shop.isLoading) })
它会在组件挂载时执行一次,之后每次依赖更新都会重新执行,适合处理各类副作用逻辑。
内容的提问来源于stack exchange,提问作者thirtythreeboas
相关产品推荐
相关产品推荐

