今天给大家分享前端新框架svelte.js开发自定义移动端弹窗组件svelte-popup。
svelte.js 全新的构建用户界面的前端框架。体积小、无虚拟dom、急速编译能力。
https://svelte.dev/
https://www.sveltejs.cn/
svelte-popup:一款基于 Svelte.js 开发的mobile弹窗组件。集合了msg、toast、alert、dialog、actionsheet等多种类型弹窗。支持 25+ 参数自定义搭配组合、组件式+函数式两种调用方式。
引入组件
import Popup, {svPopup} from '$lib/Popup'
调用方式
支持组件式和函数式两种方式调用组件。
<Popup
bind:open={isVisibleDialog}
xclose
xposition="top"
title="标题信息"
content="这里是内容信息"
btns={[
{text: '确认', style: 'color:#f60;', click: () => isVisibleDialog=false},
]}
on:open={handleOpen}
on:close={handleClose}
>
<svelte:fragment slot="content"><h3>自定义插槽内容</h3></svelte:fragment>
</Popup>
let el = svPopup({
title: '标题信息',
content: '<p style='color:#df6a16;'>这里是内容信息</p>',
xclose: true,
xposition: 'top',
shadeClose: false,
btns: [
{text: '取消', click: () => { el.$set({open: false}) }},
{text: '确认', style: 'color:#f90;', click: () => handleOK},
],
onOpen: () => {},
onClose: () => {}
})
svelte-popup编码
支持如下自定义参数配置
<script>
// 是否打开弹窗bind:open={showDialog}
export let open = false
// 弹窗标识符
// export let id = 'svpopup-' + Math.random().toString(32)
export let id = undefined
// 标题
export let title = ''
// 内容
export let content = ''
// 弹窗类型
export let type = ''
// 自定义弹窗样式
export let popupStyle = undefined
// toast图标
export let icon = ''
// 是否显示遮罩层
export let shade = true
// 点击遮罩层是否关闭
export let shadeClose = true
// 遮罩层透明度
export let opacity = ''
// 是否显示圆角
export let round = false
// 是否显示关闭图标
export let xclose = false
// 关闭图标位置
export let xposition = 'right'
// 关闭图标颜色
export let xcolor = '#333'
// 弹窗动画
export let anim = 'scaleIn'
// 弹窗位置
export let position = ''
// 长按/右键弹窗
export let follow = null
// 弹窗自动关闭时间
export let time = 0
// 弹窗层级
export let zIndex = 202203
// 弹窗按钮组
export let btns = null
/* export let btns = [
{ text: '取消', style: 'color:#aaa', disabled: true, click: null },
{ text: '确定', style: 'color:#f90', click: null }
] */
// 函数式打开|关闭回调
export let onOpen = undefined
export let onClose = undefined
// 接收函数式移除指令
export let remove = undefined
// ...
</script>
<div class="sv__popup" class:opened class:sv__popup-closed={closeCls} id={id} style="z-index: {zIndex}" bind:this={el}>
{#if bool(shade)}<div class="vui__overlay" on:click={shadeClicked} style:opacity></div>{/if}
<div class="vui__wrap">
<div class="vui__wrap-section">
<div class="vui__wrap-child {type&&'popupui__'+type} anim-{anim} {position}" class:round style="{popupStyle}">
{#if title}<div class="vui__wrap-tit">{@html title}</div>{/if}
{#if icon&&type=='toast'}<div class="vui__toast-icon">{@html toastIcon[icon]}</div>{/if}
{#if $slots.content}
<div class="vui__wrap-cnt"><slot name="content" /></div>
{:else}
{#if content}<div class="vui__wrap-cnt">{@html content}</div>{/if}
{/if}
<slot />
{#if btns}
<div class="vui__wrap-btns">
{#each btns as btn,index}
<span class="btn"style="{btn.style}" on:click={e => btnClicked(e, index)}>{@html btn.text}</span>
{/each}
</div>
{/if}
{#if xclose}<span class="vui__xclose {xposition}" style="color: {xcolor}" on:click={hide}></span>{/if}
</div>
</div>
</div>
</div>
/**
* svelte自定义手机弹框组件
*/
<script>
// ...
import { onMount, afterUpdate, createEventDispatcher, tick } from 'svelte'
const dispatch = createEventDispatcher()
let opened = false
let closeCls = undefined
let toastIcon = {
loading: '',
success: '',
fail: '',
}
const bool = (boolean) => JSON.parse(boolean) ? true : false
onMount(() => {
console.log('监听弹窗开启...')
return () => {
console.log('监听弹窗关闭...')
}
})
afterUpdate(() => {
// console.log('监听弹窗更新...')
/* if(opened) {
if(!open) {
opened = false
dispatch('close')
}
}else if(open) {
opened = true
dispatch('open')
} */
})
$: if(open) {
show()
}else {
hide()
}
/**
* 打开弹窗
*/
async function show() {
if(opened) return
opened = true
dispatch('open')
typeof onOpen == 'function' && onOpen()
zIndex = getZIndex() + 1
// 倒计时关闭
if(time) {
index++
if(timer[index] != null) clearTimeout(timer[index])
timer[index] = setTimeout(() => {
hide()
}, parseInt(time)*1000)
}
// 长按|右键菜单
if(follow) {
// ...
}
}
/**
* 关闭弹窗
*/
function hide() {
if(!opened) return
closeCls = true
setTimeout(() => {
opened = false
closeCls = false
open = false
// ...
}, 200)
}
// 点击遮罩层
function shadeClicked() {
if(bool(shadeClose)) {
hide()
}
}
// ...// 临界坐标点
function getPos(x, y, ow, oh, winW, winH) {
let l = (x + ow) > winW ? x - ow : x
let t = (y + oh) > winH ? y - oh : y
return [l, t]
}
</script>
ok,以上就是基于svelte.js开发自定义组件的一些分享。后续还会分享一些svelte实战案例。