Uni-app Vue全局模态框
思路是将模态框作为一个页面,进而可以全局显示
首先创建一个页面用来显示模态框 u-modal
<!-- pages/popup/showModal.vue -->
<template>
<view>
<!-- 使用uViewUI的u-modal -->
<u-modal
v-model="showModel"
@confirm="confirm"
@cancel="cancel"
:show-cancel-button="true"
:title="options.title"
confirm-text="Confirm"
cancel-text="Cancel"
:show-title="options.title != null && options.title !== ''"
:title-style="{
'font-size': '40rpx',
}"
>
<view class="modelContent">
<view>
<u-icon
name="question-circle"
color="#faad14"
size="38"
class="icon"
></u-icon>
{{ options.content }}
</view>
</view>
</u-modal>
</view>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from '@vue/composition-api'
export default defineComponent({
onLoad(options: any) {
// 获取配置
this.options = options
},
setup() {
const data = reactive({
showModel: true,
result: {
confirm: false,
cancel: false,
},
modelTitle: '',
options: {
title: '',
content: '',
} as Partial<UniApp.RedirectToOptions>,
})
let { showModel, result, modelTitle, options } = toRefs(data)
const closeModel = () => {
// 执行操作后,发布事件同时返回原来页面
uni.$emit('myModelResult', result)
uni.navigateBack({
delta: 1,
})
}
const cancel = () => {
result.value.cancel = true
closeModel()
}
const confirm = () => {
result.value.confirm = true
closeModel()
}
return {
closeModel,
showModel,
result,
cancel,
confirm,
modelTitle,
options,
}
},
})
</script>
<style>
/* 需要设置页面背景透明 */
page {
background: transparent;
}
</style>
<style lang="scss" scoped>
.modelContent {
padding: 30rpx 30rpx;
text-align: center;
.icon {
margin-right: 30rpx;
}
}
</style>
配置 pages.json
{
"pages": [
...
{
"path": "pages/popup/showModal",
"style": {
"navigationStyle": "custom",
"backgroundColor": "transparent",
"app-plus": {
"animationType": "fade-in",
"background": "transparent",
"popGesture": "none"
}
}
}
],
...
}
执行函数
interface ShowModalRes {
confirm: boolean;
cancel: boolean;
}
export interface ShowModalOptions {
title?: string;
content?: string;
success?: (result: ShowModalRes) => void;
fail?: (result: any) => void;
complete?: (result: any) => void;
}
export const showModal = function (options: ShowModalOptions): void {
try {
uni.navigateTo({
url: param('/pages/popup/showModal', {
title: options.title,
content: options.content
})
})
uni.$once('myModelResult', refImpl => {
if (options.success && typeof options.success === 'function') {
options.success.call(null, refImpl.value as ShowModalRes)
}
})
} catch (err) {
if (options.fail && typeof options.fail === 'function') {
options.fail.call(null, err)
}
} finally {
if (options.complete && typeof options.complete === 'function') {
options.complete.call(null, {})
}
}
uni.showModal(options)
}
function param(url: string, data: any) {
let param = ''
for (let k in data) {
let value = data[k] != null ? data[k] : ''
param += '&' + k + '=' + encodeURIComponent(value)
}
url += url.indexOf('?') < 0 ? '?' : '&'
url += param ? param.substring(1) : ''
return url
}
注入到 vue
import { showModal } from './showModal'
export default {
install(Vue: any) {
...
Vue.prototype.$showModal = showModal
}
}
声明
declare module 'vue/types/vue' {
interface Vue {
...
$showModal: (options: ShowModalOptions) => void
}
}
import Vue from 'vue'
import App from './App.vue'
import plugin from './plugin/plugin'
...
Vue.use(plugin);
new App().$mount()
使用
this.$showModal({
title: 'title'
content: 'content',
success: (res) => {
if (res.confirm) {
...
}
}
})