Uni-APP项目中的Promise挂载失效问题

文章讲述了作者在学习Uni-app时遇到Promise处理不生效的问题,详细描述了在API请求中因数据类型比较错误导致的问题,即使用!=而非==进行严格比较时遇到的困扰。作者通过老司机的帮助发现并解决了问题,提醒基础薄弱的学习者要理解数据类型转换规则,并建议通读Vue文档以加深理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 概述

说一下我这边遇到的背景,主要记录一下遇到的坑和感受;在初学Uni-app过程中很自然的会遇到Promise挂载的问题,我们也会找很多视频跟着学跟着写,发现老师们的挂在是有效的,而我们的挂载就是不起作用,不论你写多多少console.log还是判断不出来问题在哪里,甚至有些现象是反你现有认知的;这里勇敢的记录,不怕献丑;好,话不多找直接少代码说过程;

  1. 问题及处理过程

Util文件目录下新建的api.js,用于收纳请求(这里测试用的公网接口),代码如下:

然后在main.js中申明一下请求:

在async方法中调用,页面中申明调用:

逻辑、思路、代码都很简单,但是在success方法走不到,resovle方法不起作用;对着老师视频敲打了好几遍,没有发现问题,由于是业余学习,当天凌晨前也就回去了;

第二天一早九点,老司机一到就带着代码过去了,通过console大法,结合请求返回值的分析,没有超过三步到位了;原来是因为res.data.status!==1的判断有问题,!== 用来较为严格的比较,除判断数据是否不相等 ,还会判断两者数据类型是否相同,如不相同也不会转换数据类型,返回(false);

返回值中的1是一个字符串,这里代码里判断应该用res.data.status!==’1’;

  1. 小结

== 用来比较或者判断两者是否相等,比较时可以自动转换数据类型。

=== 用来较为严格的比较,除判断数据是否相等 ,还会判断两者数据类型是否相同,如不相同也不会转换数据类型,返回(false)。

顺便说一下,!= 用来比较或者判断两者是否不相等,比较时可以自动转换数据类型。

!== 用来较为严格的比较,除判断数据是否不相等 ,还会判断两者数据类型是否相同,如不相同也不会转换数据类型,返回(false);

其实不是什么大问题,但对于没有基础或则基础薄的同学们,这块可能会卡住;由此人为,要想处理这块工作,还是要把Vue通读一下作为支撑;娱乐分享,愿博一笑,祝同学们发大财!

<think>嗯,用户正在研究如何在uni-app中封装自定义模态框组件,并且提供了两个站内引用作为背景。第一个引用提到需要在接口401时触发全局模态框,第二个引用展示了一个加载组件的封装结构。看来用户的核心需求是获得一个可复用的模态框组件代码示例。用户可能正在开发需要统一UI风格的uni-app应用,内置的uni.showModal无法满足设计需求。从技术诉求看,用户需要知道三件事:组件基本结构如何搭建、如何实现全局调用、如何适配同触发场景(如401错误)。深层需求可能是想建立自己的UI组件库。对比用户提供的加载组件代码,模态框结构会更复杂,需要处理标题、内容、按钮组等元素。全局调用机制类似,但交互逻辑更丰富。考虑到用户引用中强调“自定义能力有限”,我应该在示例中重点展示高度可定制部分,比如支持传入按钮数量、自定义事件绑定等。组件封装的关键点在于:1)模板结构要预留插槽和样式钩子2)使用vue单文件组件规范3)暴露show/hide方法4)处理遮罩层交互。对于401这种特定场景,还需要在拦截器中挂载组件实例。全局注册方式用Vue.prototype最便捷,但要注意避免污染全局对象。在写示例代码时,要特别注意uni-app的环境约束,比如能使用DOM操作,样式要兼容多端。按钮事件用Promise处理会比较现代,但也要提供回调函数选项兼容旧项目。动画效果推荐用uni.createAnimation,比直接写CSS动画更稳定。用户之前可能已经封装过加载组件,所以这次可以沿用相似的架构模式。最后补上应用场景说明和常见问题,帮助用户避开实际开发中的坑。尤其要提醒小程序端的样式隔离问题,这是uni-app多端开发最容易踩的雷区。</think> 下面是在uni-app中封装全局自定义模态框组件的完整实现方案,包含示例代码和关键实现逻辑: ### 1. 组件实现(`custom-modal.vue`) ```vue <template> <view v-if="visible" class="modal-mask" @tap="closeOnMask && hide()"> <view class="modal-container" @tap.stop> <!-- 标题区 --> <view v-if="title" class="modal-header">{{ title }}</view> <!-- 内容区(支持插槽) --> <view class="modal-body"> <slot>{{ content }}</slot> </view> <!-- 按钮区 --> <view class="modal-footer"> <view v-for="(btn, index) in buttons" :key="index" :class="['modal-btn', btn.className || '']" :style="{ color: btn.color || '#606266' }" @tap="handleClick(btn)"> {{ btn.text }} </view> </view> </view> </view> </template> <script> export default { props: { title: String, content: String, buttons: { // 按钮配置 [{text: '确定', color: 'red', handler: Function}] type: Array, default: () => [{ text: '确定' }] }, closeOnMask: { // 点击遮罩关闭 type: Boolean, default: true } }, data() { return { visible: false }; }, methods: { show() { this.visible = true; }, hide() { this.visible = false; }, handleClick(btn) { if (typeof btn.handler === 'function') { const shouldClose = btn.handler() !== false; shouldClose && this.hide(); } else { this.hide(); } } } }; </script> <style scoped> .modal-mask { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 9999; display: flex; justify-content: center; align-items: center; } .modal-container { width: 80%; background-color: #fff; border-radius: 12rpx; overflow: hidden; } .modal-header { padding: 30rpx; font-size: 34rpx; font-weight: bold; text-align: center; border-bottom: 1px solid #eee; } .modal-body { padding: 40rpx 30rpx; font-size: 30rpx; line-height: 1.5; } .modal-footer { display: flex; border-top: 1px solid #eee; } .modal-btn { flex: 1; text-align: center; padding: 25rpx 0; font-size: 32rpx; } .modal-btn + .modal-btn { border-left: 1px solid #eee; } </style> ``` ### 2. 全局注册(`main.js`) ```javascript import Vue from 'vue' import CustomModal from '@/components/custom-modal.vue' // 挂载全局方法 Vue.prototype.$modal = { show(options) { // 动态创建组件实例 const Instance = Vue.extend(CustomModal); const vm = new Instance().$mount(document.createElement('div')); document.body.appendChild(vm.$el); // 合并配置参数 if (typeof options === 'string') options = { content: options }; Object.assign(vm, options); // 显示模态框 vm.show(); // 返回关闭方法 return () => { vm.hide(); setTimeout(() => document.body.removeChild(vm.$el), 300); }; } } ``` ### 3. 全局调用(401拦截示例) ```javascript // 在接口请求拦截器中 uni.addInterceptor('request', { fail: (err) => { if (err.statusCode === 401) { const closeModal = this.$modal.show({ title: '会话过期', content: '登录信息已失效,请重新登录', buttons: [ { text: '取消', handler: () => console.log('取消操作') }, { text: '去登录', color: '#07C160', handler: () => uni.navigateTo({ url: '/pages/login' }) } ] }); // 3秒后自动关闭 setTimeout(closeModal, 3000); } } }); ``` ### 4. 组件特性说明 1. **灵活按钮配置**:支持自定义按钮文字/颜色/事件 ```js buttons: [ { text: '取消', color: '#999' }, { text: '确定', color: 'blue', handler: () => {...} } ] ``` 2. **双内容模式**: ```vue <!-- 默认文本 --> <custom-modal content="提示内容"/> <!-- 复杂内容使用插槽 --> <custom-modal> <image src=".." /> <text>自定义内容</text> </custom-modal> ``` 3. **遮罩控制**:通过`closeOnMask`属性控制点击背景是否关闭 4. **动画扩展建议**: ```css .modal-container { transform: scale(0.9); transition: all 0.3s ease; } .modal-container.active { transform: scale(1); } ``` ### 5. 使用示例 ```javascript // 简单调用 this.$modal.show("操作成功!") // 完整调用 this.$modal.show({ title: '删除确认', content: '确定删除该数据?', buttons: [ { text: '取消' }, { text: '删除', color: 'red', handler: () => { console.log('执行删除操作'); return true; // 自动关闭 } } ] }) ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReaderTheEnd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值