x***@gmail.com
x***@gmail.com
  • 发布:2025-12-05 17:00
  • 更新:2025-12-05 18:28
  • 阅读:20

vue3中nexttick在组件ref赋值之后

分类:uni-app

父组件:

<template>  
    <view v-if="loading"></view>  
    <view v-if="!loading">  
        <TestComponent ref="testComponentRef"></TestComponent>  
    </view>  
</template>  

<script setup>  
    import { ref, nextTick, watch, onMounted, version } from 'vue'  
    import { onShow, onLoad } from '@dcloudio/uni-app'  

    import TestComponent from '@/components/common/test.vue'  

    const loading = ref(true)  
    const testComponentRef = ref(null)  

    watch(testComponentRef, (newVal)=>{  
        console.timeEnd('a')  
        console.log('监听器监听触发====》》》》', newVal)  
    })  

    const featchFunc = function(){  
        return new Promise((resolve, reject)=>{  
            setTimeout(()=>{  
                resolve(111)  
            }, 500)  
        })  
    }  

    const init = function(){  
        // featchFunc().then(res=>{  
        //  loading.value = false  
        //  nextTick(()=>{  
        //      console.log('nexttick回调触发=====》》》》》')  
        //      testComponentRef.value.testFun()  
        //  })  
        // })  
        loading.value = false  
        nextTick(()=>{  
            console.time('a')  
            console.log('nexttick回调触发=====》》》》》')  
            // testComponentRef.value.testFun()  
        })  
    }  

    onLoad(()=>{  
        init()  
        console.log(version)  
    })  
</script>  

<style scoped>  
</style>

子组件:

<template>  
    <view>  
        test  
    </view>  
</template>  

<script setup>  
    const testFun = function(){  
        // console.log('44444')  
    }  

    defineExpose({  
        testFun,  
    })  
</script>  

<style scoped>  
</style>

运行之后打印顺序如下:
3.4.21
test.js? [sm]:1 nexttick回调触发=====》》》》》
test.js? [sm]:1 a: 11.51220703125 ms
test.js? [sm]:1 监听器监听触发====》》》》 Proxy {__v_skip: true, testFun: ƒ}
可以看到数据的赋值在回调之后触发,这会导致nexttick之后调用组件内部的方法会报错

2025-12-05 17:00 负责人:无 分享
已邀请:
Ask小助手

Ask小助手

在 uniapp 小程序平台中,组件 ref 的赋值时机与标准 Vue 3 存在差异。当使用 v-if 控制组件渲染时,ref 的赋值可能发生在 nextTick 回调之后,这是因为小程序平台的渲染机制是异步的,DOM 更新和组件实例挂载分为多个异步阶段。

您的输出顺序证实了这一点:

  1. nextTick 回调先执行(此时 ref 仍为 null)
  2. 随后 ref 监听器才触发(组件实例已赋值)

解决方案:

  1. 推荐使用 watch 监听 ref 变化(您已有此代码),在回调中安全调用子组件方法:
    watch(testComponentRef, (newVal) => {  
     if (newVal) newVal.testFun() // 确保 ref 已赋值  
    })  
  2. 若必须在 nextTick 中调用,改用双重 nextTick
    nextTick(() => {  
     nextTick(() => {  
       testComponentRef.value?.testFun()  
     })  
    })  

原因说明:
uniapp 在小程序平台([sm])的 nextTick 实现基于小程序原生 API(如 wx.nextTick),其行为类似 setTimeout,仅保证在当前同步任务结束后执行,但不保证组件实例已挂载完成。而 ref 赋值需等待组件生命周期(如 mounted)结束,属于更晚的异步阶段。

参考文档:
uni-app nextTick API
特别说明:小程序平台需注意此异步差异,H5/App 端通常单次 nextTick 即可。

内容为 AI 生成,仅供参考
爱豆豆

爱豆豆 - 办法总比困难多

我这边看的话 顺序好像没问题 或者在详细描述一下你的问题

要回复问题请先登录注册