uni-app vue3+uniapp 组件中使用watch
uni-app vue3+uniapp 组件中使用watch
开发环境 | 版本号 | 项目创建方式 |
---|---|---|
Windows | 22631.4890 | HBuilderX |
产品分类:uniapp/App
PC开发环境操作系统:Windows
HBuilderX类型:正式
HBuilderX版本号:4.45
手机系统:iOS
手机系统版本号:iOS 14
手机厂商:苹果
手机机型:iPhone7 plus
页面类型:vue
vue版本:vue3
打包方式:云端
项目创建方式:HBuilderX
示例代码:
```vue
<script setup lang="ts">
import { RECYCLEN_METHOD, recycleMethods } from '@/constant/index'
type PropsType = {
currentMethod: {
label: string
value: RECYCLEN_METHOD
description: string
}
defaultPaymentIndex: RECYCLEN_METHOD
}
const props = withDefaults(defineProps<PropsType>(), {})
const $emits = defineEmits<{
(e: 'choosed', payment): void
}>()
const currentPaymentIndex = ref(RECYCLEN_METHOD.FIRST_PRICE)
const extractionPopupRef = ref(null)
function open() {
extractionPopupRef.value.open('bottom')
currentPaymentIndex.value = props.currentMethod.value
}
function close() {
extractionPopupRef.value.close()
}
function paymentChange(e) {
currentPaymentIndex.value = e.detail.value
}
watch(
() => props.defaultPaymentIndex,
(val) => {
if (val) {
currentPaymentIndex.value = val
}
comfirmChooseThisPayment(true)
},
{
immediate: true,
},
)
function comfirmChooseThisPayment(init = false) {
const method = recycleMethods[unref(currentPaymentIndex)]
$emits('choosed', {
...method,
})
!init && close()
}
defineExpose({
open,
close,
})
</script>
<template>
<view [@touchmove](/user/touchmove).stop.prevent>
<uni-popup ref="extractionPopupRef" :safe-area="false">
<view class="custom-popup-bottom-content">
<view>
<view class="fcc header-box">
<uni-icons class="close-icon" type="closeempty" size="22" [@click](/user/click)="close" />
<text>选择交货方式</text>
</view>
<radio-group [@change](/user/change)="paymentChange">
<label
class="delivery-item border-bottom"
v-for="(item, index) in recycleMethods"
:key="item.value"
>
<view class="fcb">
<Icon
type="img"
iconNameOrRoute="item.icon"
iconWidth="46rpx"
iconHeight="46rpx"
/>
<view class="delivery-content">
<view class="delivery-lable">{{ item.label }}</view>
<view class="delivery-des" v-if="item.description">{{ item.description }}</view>
</view>
<radio
style="transform: scale(0.9) translateX(10rpx)"
color="#E1AE58"
:value="index"
:checked="currentPaymentIndex === item.value"
/>
</view>
</label>
</radio-group>
</view>
<view class="footer-btn">
<tui-form-button [@click](/user/click)="comfirmChooseThisPayment()"> 确定 </tui-form-button>
</view>
</view>
</uni-popup>
</view>
</template>
执行打印会报错
16:51:09.381 null is not an object (evaluating 're.el=al.el')
16:51:09.381 Le@weex-main-jsfm.js:44:71934
16:51:09.381 run@weex-main-jsfm.js:23:188174
16:51:09.381 weex-main-jsfm.js:44:72239
16:51:09.381 We@weex-main-jsfm.js:44:72397
16:51:09.381 Ce@weex-main-jsfm.js:44:70377
16:51:09.381 Se@weex-main-jsfm.js:44:70072
16:51:09.381 qe@weex-main-jsfm.js:44:65984
16:51:09.381 qn@weex-main-jsfm.js:44:77259
16:51:09.381 ct@weex-main-jsfm.js:45:106975
16:51:09.381 mountPage@weex-main-jsfm.js:46:23210
16:51:09.381 of@weex-main-jsfm.js:46:212011
16:51:09.381 weex-main-jsfm.js:46:213810
16:51:09.381 Promise@[native code]
16:51:09.381 II@weex-main-jsfm.js:46:213800
16:51:09.381 weex-main-jsfm.js:46:213540
16:51:09.381 Vf@weex-main-jsfm.js:46:208801
16:51:09.381 Fv@weex-main-jsfm.js:46:213530
16:51:09.381 weex-main-jsfm.js:45:352398
16:51:09.381 Promise@[native code]
16:51:09.381 weex-main-jsfm.js:45:352387
16:51:09.381 app-service.js:110:642742
16:51:09.381 generatorResume@[native code]
16:51:09.381 Ns@app-service.js:1:642
16:51:09.381 promiseReactionJob@[native code] __ERROR
操作步骤:
从其他界面进入找个界面
预期结果:
正确结果应该会显示
实际结果:
没有显示
bug描述:
从其他界面进入到当前界面 模板试图没更新?

更多关于uni-app vue3+uniapp 组件中使用watch的实战教程也可以访问 https://www.itying.com/category-93-b0.html
1 回复
更多关于uni-app vue3+uniapp 组件中使用watch的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在uni-app Vue3中使用watch时出现模板未更新的问题,可能是由于以下几个原因导致的:
-
组件生命周期问题:确保watch在组件挂载后执行。Vue3的setup()在组件创建时同步执行,但某些DOM操作可能需要等待nextTick。
-
引用类型处理:你直接watch了一个基本类型(defaultPaymentIndex),这通常没问题,但建议使用deep选项确保深度监听:
watch(
() => props.defaultPaymentIndex,
(val) => {
// 处理逻辑
},
{ immediate: true, deep: true }
)
-
响应式数据问题:确保currentPaymentIndex正确绑定到模板。在radio组件中你使用了item.value,但checked比较的是currentPaymentIndex === item.value,需要确认两者类型一致。
-
错误处理:添加错误捕获,避免因数据问题导致整个组件渲染失败:
watch(
() => props.defaultPaymentIndex,
(val) => {
try {
if (val) {
currentPaymentIndex.value = val
}
comfirmChooseThisPayment(true)
} catch (e) {
console.error('watch error:', e)
}
},
{ immediate: true }
)