Vue中如何让script setup内的onMount()优先于其他代码执行?
解决script setup中优先加载设置的问题
你的问题核心在于script setup里的同步代码会在组件创建阶段直接执行,这时候onMount钩子还没触发,load()函数没调用,accountsettings还未初始化,直接访问settings.type自然会报错。
下面是几种可行的解决方式:
方式一:用computed属性依赖响应式数据
把依赖accountsettings的变量改成computed,利用Vue的响应式特性自动获取最新值,同时用可选链避免初始值为undefined的报错:
<script setup> import { storeToRefs } from 'pinia' import { useAccountStore } from '../stores/account.store' import { defineProps, ref, computed, onMount } from "vue"; import { useLoading } from 'vue-loading-overlay'; const accountStore = useAccountStore() const { account, error, accountsettings } = storeToRefs(accountStore) const props = defineProps({ id: { type: String, required: true, } }); // 用computed和可选链替代直接赋值 const type = computed(() => accountsettings.value?.type); async function load() { await accountStore.loadSettings(); if (props.id) { await accountStore.loadAccount(props.id); } }; onMount(() => { console.log('mounting...'); load(); }); </script>
之后使用type时直接取type.value即可,它会在accountsettings加载完成后自动更新。
方式二:把依赖逻辑移到设置加载完成后
如果业务逻辑必须在设置加载完成后执行,可以把相关代码放到load函数里,或者用watch监听accountsettings的变化:
<script setup> // ... 其他导入和定义不变 let type; async function load() { await accountStore.loadSettings(); // 加载完成后再获取type type = accountsettings.value.type; // 此处执行依赖type的其他函数 if (props.id) { await accountStore.loadAccount(props.id); } }; onMount(() => { console.log('mounting...'); load(); }); // 或者用watch监听,当accountsettings有值时执行逻辑 watch(accountsettings, (newSettings) => { if (newSettings) { type = newSettings.type; // 执行相关业务逻辑 } }, { immediate: true }); // immediate选项会在组件初始化时就检查一次 </script>
方式三:使用顶层await(异步组件)
如果希望在组件渲染前就完成设置加载,可以用顶层await直接调用加载函数,但这样组件会变成异步组件,需要父组件用<Suspense>包裹:
<script setup> import { storeToRefs } from 'pinia' import { useAccountStore } from '../stores/account.store' import { defineProps } from "vue"; const accountStore = useAccountStore() const { account, error, accountsettings } = storeToRefs(accountStore) const props = defineProps({ id: { type: String, required: true, } }); // 顶层await,组件初始化时直接加载设置 await accountStore.loadSettings(); if (props.id) { await accountStore.loadAccount(props.id); } // 此时accountsettings已经有值,可以安全访问 const settings = accountsettings.value; let type = settings.type; // ... 其他函数 </script>
父组件使用时需要包裹:
<Suspense> <YourComponent id="xxx" /> <template #fallback> <!-- 加载中提示 --> <div>加载中...</div> </template> </Suspense>
内容的提问来源于stack exchange,提问作者Jyina
相关产品推荐
相关产品推荐

