对uni_modules/uview-plus/components/u-toast进行修改,原生语法是vue2,现在改成vue3,修改template和script
<template>
<view class="u-toast">
<u-overlay :show="data.isShow" :custom-style="overlayStyle">
<view class="u-toast__content" :style="[contentStyle]"
:class="['u-type-' + data.tmpConfig.type, (data.tmpConfig.type === 'loading' || data.tmpConfig.loading) ? 'u-toast__content--loading' : '']">
<u-loading-icon v-if="data.tmpConfig.type === 'loading'" mode="circle" color="rgb(255, 255, 255)"
inactiveColor="rgb(120, 120, 120)" size="25"></u-loading-icon>
<u-icon v-else-if="data.tmpConfig.type !== 'defalut' && iconName" :name="iconName" size="17"
:color="data.tmpConfig.type" :customStyle="iconStyle"></u-icon>
<u-gap v-if="data.tmpConfig.type === 'loading' || data.tmpConfig.loading" height="12"
bgColor="transparent"></u-gap>
<text class="u-toast__content__text" :class="['u-toast__content__text--' + data.tmpConfig.type]"
style="max-width: 400rpx;">{{ data.tmpConfig.message }}</text>
</view>
</u-overlay>
</view>
</template>
<script setup>
import mpMixin from '../../libs/mixin/mpMixin.js';
import mixin from '../../libs/mixin/mixin.js';
import {
computed,
onBeforeUnmount,
reactive
} from 'vue'
const data = reactive({
isShow: false,
timer: null, // 定时器
config: {
message: '', // 显示文本
type: '', // 主题类型,primary,success,error,warning,black
duration: 2000, // 显示的时间,毫秒
icon: true, // 显示的图标
position: 'center', // toast出现的位置
complete: null, // 执行完后的回调函数
overlay: false, // 是否防止触摸穿透
loading: false, // 是否加载中状态
},
tmpConfig: {}, // 将用户配置和内置配置合并后的临时配置变量
})
const iconName = computed(() => {
// 只有不为none,并且type为error|warning|succes|info时候,才显示图标
if (!data.tmpConfig.icon || data.tmpConfig.icon == 'none') {
return '';
}
if (['error', 'warning', 'success', 'primary'].includes(data.tmpConfig.type)) {
return uni.$u.type2icon(data.tmpConfig.type)
} else {
return ''
}
})
const overlayStyle = computed(() => {
const style = {
justifyContent: 'center',
alignItems: 'center',
display: 'flex'
}
// 将遮罩设置为100%透明度,避免出现灰色背景
style.backgroundColor = 'rgba(0, 0, 0, 0)'
return style
})
const iconStyle = computed(() => {
const style = {}
// 图标需要一个右边距,以跟右边的文字有隔开的距离
style.marginRight = '4px'
// #ifdef APP-NVUE
// iOSAPP下,图标有1px的向下偏移,这里进行修正
if (uni.$u.os() === 'ios') {
style.marginTop = '-1px'
}
// #endif
return style
})
const loadingIconColor = computed(() => {
let color = 'rgb(255, 255, 255)'
if (['error', 'warning', 'success', 'primary'].includes(data.tmpConfig.type)) {
// loading-icon组件内部会对color参数进行一个透明度处理,该方法要求传入的颜色值
// 必须为rgb格式的,所以这里做一个处理
color = uni.$u.hexToRgb(uni.$u.color[data.tmpConfig.type])
}
return color
})
const contentStyle = computed(() => {
const windowHeight = uni.$u.sys().windowHeight,
style = {}
let value = 0
// 根据top和bottom,对Y轴进行窗体高度的百分比偏移
if (data.tmpConfig.position === 'top') {
value = -windowHeight * 0.25
} else if (data.tmpConfig.position === 'bottom') {
value = windowHeight * 0.25
}
style.transform = `translateY(${value}px)`
return style
})
function onCreated() {
// 通过主题的形式调用toast,批量生成方法函数
['primary', 'success', 'error', 'warning', 'default', 'loading'].map(item => {
data[item] = message => show({
type: item,
message
})
})
}
onCreated()
onBeforeUnmount(() => {
clearTimer()
})
const show = function(options) {
// 不将结果合并到data.config变量,避免多次调用u-toast,前后的配置造成混乱
data.tmpConfig = uni.$u.deepMerge(data.config, options)
// 清除定时器
clearTimer()
data.isShow = true
data.timer = setTimeout(() => {
// 倒计时结束,清除定时器,隐藏toast组件
clearTimer()
// 判断是否存在callback方法,如果存在就执行
typeof(data.tmpConfig.complete) === 'function' && data.tmpConfig.complete()
}, data.tmpConfig.duration)
}
const hide = function() {
clearTimer()
}
const clearTimer = function() {
data.isShow = false
// 清除定时器
clearTimeout(data.timer)
data.timer = null
}
defineExpose({
show,
hide,
clearTimer
})
</script>
使用方法
<template>
<view>
<u-toast ref="toast"></u-toast>
<u-button text="发布" @click="publish"></u-button>
</view>
</template>
<script setup>
import {
ref
} from "vue";
const toast = ref()
function publish(){
toast.value.show({
type: 'success',
message: "庄生晓梦迷蝴蝶",
})
}
</script>