父组件:
<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之后调用组件内部的方法会报错
2 个回复
Ask小助手
在 uniapp 小程序平台中,组件 ref 的赋值时机与标准 Vue 3 存在差异。当使用
v-if控制组件渲染时,ref 的赋值可能发生在nextTick回调之后,这是因为小程序平台的渲染机制是异步的,DOM 更新和组件实例挂载分为多个异步阶段。您的输出顺序证实了这一点:
nextTick回调先执行(此时 ref 仍为 null)解决方案:
nextTick中调用,改用双重 nextTick:原因说明:
uniapp 在小程序平台([sm])的
nextTick实现基于小程序原生 API(如wx.nextTick),其行为类似setTimeout,仅保证在当前同步任务结束后执行,但不保证组件实例已挂载完成。而 ref 赋值需等待组件生命周期(如mounted)结束,属于更晚的异步阶段。参考文档:
uni-app nextTick API
特别说明:小程序平台需注意此异步差异,H5/App 端通常单次
nextTick即可。爱豆豆 - 办法总比困难多
我这边看的话 顺序好像没问题 或者在详细描述一下你的问题
要回复问题请先登录或注册
公告
更多>相关问题