'# uni.showToast 的样式怎么写
一、背景与问题
在 uni-app 开发中,uni.showToast 是最常用的提示方法之一。但开发者在实际使用时常常遇到这样的问题:默认的提示样式无法满足业务需求,比如需要改变背景色、字体大小、图标样式,或者需要支持自定义动画效果。
然而,uni-app 的官方 API 对 uni.showToast 的样式控制非常有限。开发者如果想要自定义样式,必须通过底层原理进行改造。本文将深入解析 uni.showToast 的实现原理,并给出完整的解决方案。
二、基本原理
uni.showToast 是 uni-app 通过调用原生模块实现的。在底层,它会根据平台(微信小程序、H5、App)生成对应的提示框。不同平台的实现差异较大,但核心逻辑是通过 uni.createSelectorQuery 创建 DOM 节点,并通过 wx.showLoading 或 wx.showToast 等原生 API 控制显示。
由于 uni-app 的组件化架构,开发者可以通过自定义组件或覆盖默认样式来实现样式自定义。但需要注意以下几点:
- 原生 API 的限制:原生模块对样式控制非常有限,某些平台(如微信小程序)不允许直接修改提示框样式
- 跨平台一致性:不同平台的样式表现可能差异较大,需要做适配处理
- 性能开销:频繁创建 DOM 节点可能影响性能
三、环境准备
确保你的开发环境满足以下条件:
- 安装最新版 uni-app(推荐 3.5.0+)
- 使用 Vue 3 或 Vue 2(根据项目版本选择)
- 配置好对应平台(微信小程序/ H5/ App)
四、核心实现
1. 基础样式覆盖
通过 CSS 覆盖默认样式是最简单的方式,但需要使用 !important 强制覆盖:
<template>
<view class="custom-toast">
<text class="toast-text">自定义提示</text>
</view>
</template>
<style>
.custom-toast {
background-color: #ff0000 !important;
color: white !important;
font-size: 16px !important;
}
</style>关键代码解释:
!important是必须的,因为 uni-app 的默认样式具有更高优先级- 样式需要作用于
uni.showToast创建的 DOM 节点 - 该方法仅适用于 H5 平台,小程序不支持 CSS 覆盖
2. 自定义组件方案
创建可复用的自定义 toast 组件,通过动态绑定样式实现更灵活的控制:
<!-- CustomToast.vue -->
<template>
<view class="custom-toast" :style="customStyle">
<text class="toast-text">{{ message }}</text>
</view>
</template>
<script>
export default {
props: {
message: String,
backgroundColor: {
type: String,
default: '#ff0000'
},
color: {
type: String,
default: 'white'
}
},
computed: {
customStyle() {
return {
backgroundColor: this.backgroundColor,
color: this.color
};
}
}
};
</script>
<style>
.custom-toast {
padding: 20rpx;
border-radius: 16rpx;
text-align: center;
font-size: 28rpx;
}
</style>关键代码解释:
- 使用 props 动态传递样式参数
- 通过 computed 属性生成最终样式对象
- 可通过
:style绑定动态样式
3. 原生 API 拦截方案(高级)
通过 uni.createSelectorQuery 直接操作原生 DOM 节点:
uni.showToast({
title: '自定义提示',
duration: 2000,
success: (res) => {
const query = uni.createSelectorQuery();
query.select('.uni-toast').boundingClientRect(res => {
if (res) {
// 获取原生 DOM 节点
const node = res;
node.style.backgroundColor = '#ff0000';
node.style.color = 'white';
}
}).exec();
}
});关键代码解释:
- 使用
select方法获取 toast 元素 - 通过
boundingClientRect获取 DOM 节点 - 可直接修改样式属性(仅适用于 H5 平台)
五、完整案例
1. 自定义 toast 组件的完整实现
<!-- pages/index/index.vue -->
<template>
<view class="container">
<button @click="showToast">显示自定义提示</button>
<custom-toast
v-if="show"
:message="toastMessage"
:backgroundColor="toastBgColor"
:color="toastColor"
@close="closeToast" />
</view>
</template>
<script>
import CustomToast from '@/components/CustomToast.vue';
export default {
components: { CustomToast },
data() {
return {
show: false,
toastMessage: '自定义提示内容',
toastBgColor: '#ff0000',
toastColor: 'white'
};
},
methods: {
showToast() {
this.show = true;
setTimeout(() => {
this.closeToast();
}, 2000);
},
closeToast() {
this.show = false;
}
}
};
</script>
<style>
.container {
padding: 40rpx;
}
</style><!-- components/CustomToast.vue -->
<template>
<view class="custom-toast" :style="customStyle" @touchstart="close">
<text class="toast-text">{{ message }}</text>
</view>
</template>
<script>
export default {
props: {
message: String,
backgroundColor: {
type: String,
default: '#ff0000'
},
color: {
type: String,
default: 'white'
}
},
computed: {
customStyle() {
return {
backgroundColor: this.backgroundColor,
color: this.color
};
}
},
methods: {
close() {
this.$emit('close');
}
}
};
</script>
<style>
.custom-toast {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 20rpx 40rpx;
border-radius: 16rpx;
text-align: center;
font-size: 28rpx;
}
</style>关键点说明:
- 使用组件化封装,提高复用性
- 支持动态样式控制
- 增加触摸关闭功能
- 支持跨平台使用
六、源码解析
以 H5 平台为例,分析 uni.showToast 的实现原理:
// uni-app 的底层实现(简化版)
function showToast(options) {
const toast = document.createElement('div');
toast.className = 'uni-toast';
toast.innerHTML = options.title;
// 添加样式
toast.style.backgroundColor = '#fff';
toast.style.color = '#000';
document.body.appendChild(toast);
setTimeout(() => {
toast.remove();
}, options.duration);
}关键点解析:
- 创建了自定义的
div节点 - 设置了默认样式
- 通过
setTimeout控制显示时间 - 最终通过
remove移除节点
七、进阶使用
1. 动画效果实现
<template>
<view class="custom-toast" :style="customStyle" @touchstart="close">
<text class="toast-text">{{ message }}</text>
</view>
</template>
<script>
export default {
methods: {
close() {
this.$emit('close');
}
}
};
</script>
<style>
.custom-toast {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>2. 多样式支持
// 通过 props 支持多种样式
props: {
message: String,
type: {
type: String,
default: 'default',
validator: value => ['default', 'success', 'error', 'loading'].includes(value)
}
},
computed: {
customStyle() {
const base = {
padding: '20rpx 40rpx',
borderRadius: '16rpx',
textAlign: 'center',
fontSize: '28rpx'
};
if (this.type === 'success') {
return { ...base, backgroundColor: '#00ff00', color: 'white' };
} else if (this.type === 'error') {
return { ...base, backgroundColor: '#ff0000', color: 'white' };
} else if (this.type === 'loading') {
return { ...base, backgroundColor: '#0000ff', color: 'white' };
}
return base;
}
}八、性能与工程实践
1. 性能优化
- 避免频繁创建 DOM 节点
- 使用缓存机制复用 toast 实例
- 控制 toast 显示时间(建议 2000ms 以内)
- 避免在滚动过程中频繁显示 toast
2. 异常处理
try {
uni.showToast({
title: '操作成功',
duration: 2000,
success: () => {
// 处理成功逻辑
},
fail: (err) => {
console.error('toast 显示失败:', err);
}
});
} catch (e) {
console.error('调用 toast 时发生错误:', e);
}3. 安全风险
- 样式覆盖可能导致 UI 不一致
- 频繁创建 DOM 节点可能影响页面性能
- 未正确处理 toast 的关闭逻辑可能导致内存泄漏
九、常见问题与踩坑
1. 样式未生效问题
错误示例:
.toast {
background-color: red;
}问题分析:
- 选择器未正确匹配 uni-app 生成的类名
- 缺少
!important强制覆盖 - 未在正确的作用域中定义样式
解决方法:
.uni-toast {
background-color: red !important;
}2. 小程序平台不生效
错误示例:
<template>
<view class="toast">提示内容</view>
</template>问题分析:
- 微信小程序不支持 CSS 覆盖
- 需要使用自定义组件方案
解决方法:
<template>
<custom-toast message="提示内容" />
</template>3. 多个 toast 重叠问题
错误示例:
uni.showToast({ title: '提示1' });
uni.showToast({ title: '提示2' });问题分析:
- 默认情况下会显示两个 toast
- 可能导致 UI 重叠
解决方法:
uni.showLoading({ title: '加载中...' });
// 操作完成后
uni.hideLoading();十、最佳实践
- 简单提示:直接使用
uni.showToast,无需自定义样式 - 复杂需求:使用自定义组件方案,通过 props 控制样式
- 动画需求:使用 CSS 动画实现更丰富的视觉效果
- 性能敏感场景:使用缓存机制,避免频繁创建 DOM 节点
- 跨平台开发:优先考虑组件化方案,确保样式一致性
十一、总结
uni.showToast 的样式自定义是 uni-app 开发中的常见需求,但需要理解其底层实现原理。通过自定义组件、CSS 覆盖或原生 API 拦截等方式,可以实现高度定制化的提示效果。在实际开发中,应根据具体需求选择合适的方案:
- 简单提示:直接使用默认样式
- 中等需求:使用自定义组件方案
- 复杂需求:结合 CSS 动画和 props 控制
- 性能敏感场景:使用缓存和优化策略
开发过程中需要注意不同平台的差异,避免样式不一致的问题。同时,要合理控制 toast 的显示频率,避免影响用户体验。通过合理的架构设计和代码组织,可以实现既美观又高效的提示系统。