问题探索:某些场景下H5页面能够触发,而uniapp微信小程序不能触发

问题重现

在使用uniapp开发微信小程序时,甲方要求将toast改为弹窗展示,并增加按钮用于跳转到电话界面,跳转到电话界面的逻辑很好做,使用uniapp自带的如下命令或者找AI写能够轻松搞定:

javascript 复制代码
const contact = () => {
  uni.makePhoneCall({
    phoneNumber: '123456789',
    fail: (err) => {
      console.error('拨打电话失败:', err);
    },
  });
}

但是toast改为弹窗展示的这一部分遇到了一些问题,最初我使用传统的vue3代码逻辑来写,先用props+emits的方法来解决,部分伪代码如下:

子组件

html 复制代码
<template>
  <su-popup :show="props?.show"@close="props.show = false">
    ...
</template>

<script setup>
import { reactive, computed, defineProps, defineEmits } from 'vue';
...
// 负责展示
const props = defineProps({
  show: false,
});

const emits = defineEmits();

const closeModal = () => {
  emits('close');
};
...
</script>

父组件

html 复制代码
<template>
    <s-lvl-modal :show="state?.show" @close="state?.show=false" />
</template>
<script setup>
const state= reactive({ show: false, })
// 触发弹窗的逻辑
state?.show=true
...
</script>

但是这种方式下H5模式下可以跳出弹窗,而微信小程序无法弹窗

问题探索

为了解决这个问题,我先求助于deepseek,它给出的代码是这样的

父组件

html 复制代码
<!-- 父组件修改后 -->
<template>
    <s-lvl-modal :show="state.show" @close="closeModal" />
    <!-- 其他内容不变 -->
</template>

<script setup>
import { reactive } from 'vue';
import sLvlModal from './s-lvl-modal.vue'; // 确保路径正确

const state = reactive({
    show: false
});

const closeModal = () => {
    state.show = false;
}
// 其他逻辑不变
</script>

子组件

html 复制代码
<!-- 子组件修改后 -->
<script setup>
import { ref, watch } from 'vue';

// props定义
const props = defineProps({
  show: Boolean
});

// 创建响应式变量
const showProp = ref(props.show);

// 监听props变化
watch(() => props.show, (val) => {
  showProp.value = val;
});

// emits定义不变
</script>

<template>
  <su-popup 
    :show="showProp"
    type="center" 
    round="10"
    @close="closeModal"
    :isMaskClick="false"
    maskBackgroundColor="rgba(0, 0, 0, 0.7)"
  >
    <!-- 内容不变 -->
  </su-popup>
</template>

结果报错如下:

ini 复制代码
AppOnError: TypeError: Cannot read property 'openModal' of null
    at toCommission (<anonymous>:47:26)
    at callWithErrorHandling (vendor.js?t=wechat&s=1753756936479&v=edf8366d112d96098f5089ed6f3e1306:3616)
    at callWithAsyncErrorHandling (vendor.js?t=wechat&s=1753756936479&v=edf8366d112d96098f5089ed6f3e1306:3623)
    at t.invoke2 (vendor.js?t=wechat&s=1753756936479&v=edf8366d112d96098f5089ed6f3e1306:7035)
    at f (WASubContext.js?t=wechat&s=1753756936479&v=3.8.9:1)
    at WASubContext.js?t=wechat&s=1753756936479&v=3.8.9:1
    at t.<anonymous> (WASubContext.js?t=wechat&s=1753756936479&v=3.8.9:1)
    at Function.<anonymous> (WASubContext.js?t=wechat&s=1753756936479&v=3.8.9:1)

解决方法

最后迫不得已,使用expose的方法进行解决,去掉props和emits的传递,子组件伪代码如下:

html 复制代码
<template>
  <su-popup :show="state.show" @close="closeModal()">
  ...
</template>
<script setup>
import { reactive,defineExpose } from 'vue';
...
const state = reactive({
  show: false,
  ...
});

const openModal = () => {
  state.show = true;
}

const closeModal = () => {
  state.show = false;
};
...
defineExpose({
  openModal,
  closeModal
});
</script>

父组件的伪代码如下:

html 复制代码
<template>
    <s-lvl-modal ref="lvlModalRef" />
</template>
<script setup>
import { ref } from 'vue';
import lvlModal from './s-lvl-modal.vue';
const lvlModalRef = ref(null);
// 触发弹窗的逻辑
lvlModalRef.value?.openModal();
...
</script>

之后再用微信开发者工具进行测试,解决

相关推荐
计算机魔术师8 分钟前
Fable 5.1 来了,智能体任务成本降 45%——Anthropic 这次为何降价这么狠
前端
Csvn9 分钟前
现代 CSS 新特性深度:container query、:has()、@scope 与 subgrid
前端
计算机魔术师14 分钟前
Anthropic 自己承认:模型越来越难管住了
前端
两只羊ovo23 分钟前
Agent 干活的底层地基:path 路径 + fs 文件系统,一次讲透
前端
一用书生23 分钟前
我给 ChatGPT、DeepSeek、Kimi 都加了一个「保存为笔记」按钮
前端·ai编程·vibecoding
咖啡无伴侣26 分钟前
1. 从零搭建企业级 Monorepo 工程化模板:初始化、应用创建与共享 TypeScript 配置
前端·前端框架
moonsims27 分钟前
再议AiBrainBox-V的前左右三目布局-满足多目SLAM算法;对比单下视VIO(低空、地面纹理丰富、飞行速度适中无人机 )&多目VIO
前端·人工智能·量子计算
AI编程实验室27 分钟前
Agent Handoff 自动跟踪 Skill:安装、事件映射与证据分级
前端·ai编程
KoPa28 分钟前
HeySmart:事件总线——异步解耦的艺术
前端·后端
金花顺29 分钟前
ndroid 音频系统:AudioTrack 源码深度解析(从 Java 构造到 Native 启动)
前端·架构