android6 全局对话框,vue3.0自定义组件|vue3仿android/ios弹框|Vue3.x全局对话框

介绍

前几天有给大家分享一个vue2弹框组件,今天主要分享的是Vue3.0实现轻量级移动端自定义弹出框组件V3Popup。

AAffA0nNPuCLAAAAAElFTkSuQmCC

V3Popup 一款基于vue3.0开发的移动端自定义弹出层组件。

内置20+种参数配置、7+弹窗类型、6+弹窗动画

支持 msg、dialog、modal、actionSheet、toast、android/ios 等弹窗类型。

并且在功能效果及UI上和之前的vue2保持一致。

AAffA0nNPuCLAAAAAElFTkSuQmCC

快速引入

在main.js中引入v3popup组件。

import { createApp } from 'vue'

import App from './App.vue'

// 引入弹窗组件v3popup

import V3Popup from './components/v3popup'

createApp(App).use(V3Popup).mount('#app')

支持组件式和函数式两种灵活调用方式。

content="

确认框(这里是确认框提示信息,这里确认框提示信息,这里是确认框提示信息)
"

:btns="[

{text: '取消', click: () => showConfirm=false},

{text: '确定', style: 'color:#f90;', click: handleInfo},

]"

/>

函数式写法如下:

let $el = this.$v3popup({

title: '标题',

content: '

这里是内容信息!
',

type: 'android',

shadeClose: false,

xclose: true,

btns: [

{text: '取消', click: () => { $el.close(); }},

{text: '确认', style: 'color:#f90;', click: () => handleOK},

],

onSuccess: () => {},

onEnd: () => {}

})

在vue3.0中提供了两种可供全局调用的方法。app.config.globalProperties 和 app.provide

1、通过 app.config.globalProperties.$v3popup = V3Popup 这种方式挂载

// vue2.x中调用

methods: {

showDialog() {

this.$v3popup({...})

}

}

// vue3.x中调用

setup() {

// 获取上下文

const { ctx } = getCurrentInstance()

ctx.$v3popup({...})

}

2、通过 app.provide('v3popup', V3Popup)这种方式

// vue2.x中调用

methods: {

showDialog() {

this.v3popup({...})

}

}

// vue3.x中调用

setup() {

const v3popup = inject('v3popup')

const showDialog = () => {

v3popup({...})

}

return {

v3popup,

showDialog

}

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

AAffA0nNPuCLAAAAAElFTkSuQmCC

编码实现

在vue3中既可以通过vue2的optionAPI写法来实现,也可以通过setup来写。既然是vue3,就通过vue3语法写了。

/**

* @Desc Vue3.0自定义弹层V3Popup

* @Time andy by 2020-12

* @About Q:282310962 wx:xy190310

*/

import { onMounted, ref, reactive, watch, toRefs, nextTick } from 'vue'

let $index = 0, $locknum = 0, $timer = {}

export default {

props: {

// 接收父组件v-model值,如果v-model:open,则这里需写open: {...}

modelValue: { type: Boolean, default: false },

// 标识符,相同ID共享一个实例

id: {

type: String, default: ''

},

title: String,

content: String,

type: String,

popupStyle: String,

icon: String,

shade: { type: [Boolean, String], default: true },

shadeClose: { type: [Boolean, String], default: true },

opacity: { type: [Number, String], default: '' },

round: Boolean,

xclose: Boolean,

xposition: { type: String, default: 'right' },

xcolor: { type: String, default: '#333' },

anim: { type: String, default: 'scaleIn' },

position: String,

follow: { type: Array, default: null },

time: { type: [Number, String], default: 0 },

zIndex: { type: [Number, String], default: '8080' },

teleport: [String, Object],

btns: {

type: Array, default: null

},

onSuccess: { type: Function, default: null },

onEnd: { type: Function, default: null },

},

emits: [

'update:modelValue'

],

setup(props, context) {

const elRef = ref(null)

const data = reactive({

opened: false,

closeCls: '',

toastIcon: {

...

}

})

onMounted(() => {

...

})

// 监听弹层v-model

watch(() => props.modelValue, (val) => {

if(val) {

open()

}else {

close()

}

})

// 打开弹层

const open = () => {

if(data.opened) return

data.opened = true

typeof props.onSuccess === 'function' && props.onSuccess()

const dom = elRef.value

dom.style.zIndex = getZIndex() + 1

...

// 倒计时

if(props.time) {

$index++

// 避免重复操作

if($timer[$index] !== null) clearTimeout($timer[$index])

$timer[$index] = setTimeout(() => {

close()

}, parseInt(props.time) * 1000)

}

// 长按|右键菜单

if(props.follow) {

...

}

}

// 关闭弹层

const close = () => {

if(!data.opened) return

data.closeCls = true

setTimeout(() => {

...

context.emit('update:modelValue', false)

typeof props.onEnd === 'function' && props.onEnd()

}, 200)

}

// 点击遮罩层

const shadeClicked = () => {

if(JSON.parse(props.shadeClose)) {

close()

}

}

// 按钮事件

const btnClicked = (e, index) => {

let btn = props.btns[index];

if(!btn.disabled) {

typeof btn.click === 'function' && btn.click(e)

}

}

...

return {

...toRefs(data),

elRef,

close,

shadeClicked,

btnClicked,

}

}

}

上面就是vue3实现弹窗的模板及核心逻辑处理部分。

AAffA0nNPuCLAAAAAElFTkSuQmCC

在vue3.0中可以通过 createApp 或 createVNode render 来实现函数式写法。将弹框实例挂载到body上面。

import { createApp } from 'vue'

import PopupConstructor from './popup.vue'

let $inst

// 创建挂载实例

let createMount = (opts) => {

const mountNode = document.createElement('div')

document.body.appendChild(mountNode)

const app = createApp(PopupConstructor, {

...opts, modelValue: true,

remove() {

app.unmount(mountNode)

document.body.removeChild(mountNode)

}

})

return app.mount(mountNode)

}

function V3Popup(options = {}) {

options.id = options.id || 'v3popup_' + generateId()

$inst = createMount(options)

return $inst

}

V3Popup.install = app => {

app.component('v3-popup', PopupConstructor)

// app.config.globalProperties.$v3popup = V3Popup

app.provide('v3popup', V3Popup)

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

okey,基于vue3.x开发自定义弹框组件就介绍这么多。感谢大家的阅读。

结语

如果你觉得这篇内容对你有启发或帮助,那么可以帮我三个小忙:

转发/点赞,让更多的人也能看到这篇分享。

加关注、不迷路,不定期分享原创技术知识。

也看看其它历史文章。

AAffA0nNPuCLAAAAAElFTkSuQmCC

你可能感兴趣的:(android6,全局对话框)