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描述:
从其他界面进入到当前界面   模板试图没更新?

![](https://www.itying.com/uniimg.php?url=https://img-cdn-tc.dcloud.net.cn/uploads/questions/20250219/bfd4e2997272482680079c570f479c31.png)

更多关于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时出现模板未更新的问题,可能是由于以下几个原因导致的:

  1. 组件生命周期问题:确保watch在组件挂载后执行。Vue3的setup()在组件创建时同步执行,但某些DOM操作可能需要等待nextTick。

  2. 引用类型处理:你直接watch了一个基本类型(defaultPaymentIndex),这通常没问题,但建议使用deep选项确保深度监听:

watch(
  () => props.defaultPaymentIndex,
  (val) => {
    // 处理逻辑
  },
  { immediate: true, deep: true }
)
  1. 响应式数据问题:确保currentPaymentIndex正确绑定到模板。在radio组件中你使用了item.value,但checked比较的是currentPaymentIndex === item.value,需要确认两者类型一致。

  2. 错误处理:添加错误捕获,避免因数据问题导致整个组件渲染失败:

watch(
  () => props.defaultPaymentIndex,
  (val) => {
    try {
      if (val) {
        currentPaymentIndex.value = val
      }
      comfirmChooseThisPayment(true)
    } catch (e) {
      console.error('watch error:', e)
    }
  },
  { immediate: true }
)
回到顶部