Vue Composition API:如何将onBeforeMount中获取的响应式变量正确传入composable?
Vue Composition API异步响应式数据传递问题解决方案
错误根源分析
- 响应式API使用错误:
useProduct中用reactive声明的product无需使用.value赋值,reactive返回的是响应式对象本身,直接对product.value赋值会得到undefined。如果需要直接替换整个对象,建议将product改为ref声明,或者使用Object.assign(product, response.data)更新reactive对象。 - 拼写错误:组件中调用
useProductDetails时传入的参数是prodcut,拼写错误少了一个字母t,会导致传入undefined。 - 异步时序问题:
setup是同步执行的,调用useProductDetails时异步请求还未触发,product还是初始空值,直接访问内部属性就会抛出未定义错误。
可行解决方案
方案1:调整useProduct实现+改造useProductDetails支持响应式依赖
首先修正useProduct的响应式写法:
// useProduct.js export default function useProduct() { // 改用ref声明,支持直接替换整个对象 const product = ref({}) async function getProduct(id) { try{ const response = await {{http Request}} product.value = response.data }catch(err) { console.log(err) } } return {product, getProduct} }
然后改造useProductDetails,所有派生属性用computed包裹,结合可选链兼容空值状态:
// useProductDetails.js export default function useProductDetails(product) { // 传入的product是ref类型,访问时加.value,用可选链避免空值报错 const productAlias = computed(() => product.value?.alias ?? '') const productTitle = computed(() => product.value?.title ?? '') const createdAt = computed(() => product.value?.createdAt ?? '') // 其余属性同理 return { productAlias, productTitle, createdAt } }
组件代码无需调整,派生属性会自动随着product异步赋值后更新。
方案2:异步请求完成后再初始化派生属性
如果不想改造useProductDetails,可以在组件中监听product的变化,等数据返回后再初始化:
setup(_, {root}) { const loading = ref(false) const { product, getProduct} = useProduct() // 先声明响应式变量存储派生属性 const productDetails = ref({}) const {productAlias, productTitle, createdAt} = toRefs(productDetails) onBeforeMount(async () => { loading.value = true await getProduct(root.$route.params.id) // 数据返回后再调用useProductDetails productDetails.value = useProductDetails(product) loading.value = false }) return {loading, product, productAlias, productTitle, createdAt} }
同时在模板中给用到这些属性的节点加上v-if="!loading",避免空值渲染报错。
内容的提问来源于stack exchange,提问作者marciado
相关产品推荐
相关产品推荐

