前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于Svelte.js弹窗插件svelte-popup

基于Svelte.js弹窗插件svelte-popup

原创
作者头像
andy2018
发布2022-03-19 08:00:26
7.7K0
发布2022-03-19 08:00:26
举报
文章被收录于专栏:h5h5

今天给大家分享一个前端新宠框架svelte.js开发自定义组件实现方式。

前段时间有分享一个svelte自定义导航条+菜单栏(Tabbar/Navbar)组件。这次分享一个svelte开发自定义弹框sveltePopup插件。

svelte-popup:基于 Svelte.js 开发的移动端弹窗组件。汇集了info、toast、alert、dialog、contextmenu等多种类型弹窗。支持25+参数自定义搭配组合、组件式+函数式两种调用方式。

快速引入

代码语言:javascript
复制
import Popup, {svPopup} from '$lib/Popup'
  • 组件方式调用
代码语言:javascript
复制
<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>
  • 函数方式调用
代码语言:javascript
复制
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: () => {}
})

对于一些简单的效果可以使用函数方式调用,一些复杂的展示可以使用组件slot插槽方式调用。并且支持函数+组件混合调用。

代码语言:javascript
复制
<!-- ActionSheet底部弹出式菜单 -->
<Popup bind:open={showActionSheet} anim="footer" type="actionsheet" zIndex="2020"
    content="弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内"
    btns={[
        {text: '拍照', style: 'color:#09f;', disabled: true, click: handleInfo},
        {text: '从手机相册选择', style: 'color:#00e0a1;', click: handleInfo},
        {text: '保存图片', style: 'color:#e63d23;', click: () => null},
        {text: '取消', click: () => showActionSheet=false},
    ]}
/>

<!-- Ios样式 -->
<Popup bind:open={showIos1} type="ios" shadeClose="false" title="标题内容" zIndex="1990"
    content="弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内"
    btns={[
        {text: '知道了', click: () => showIos1=false},
        {text: '确定', style: 'color:#00e0a1;', click: handleInfo},
    ]}
>
</Popup>
代码语言:javascript
复制
<!-- Android样式 -->
<Popup bind:open={showAndroid1} type="android" shadeClose="false" xclose title="标题内容" zIndex="2000"
    content="弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内"
    btns={[
        {text: '知道了', click: () => showAndroid1=false},
        {text: '确定', style: 'color:#00e0a1;', click: handleInfo},
    ]}
>
</Popup>

<!-- Android样式2(无标题) -->
<Popup bind:open={showAndroid2} type="android"
    content="在设置-应用-权限中开启位置信息权限,为您推荐本地资讯"
    btns={[
        {text: '取消', click: () => showAndroid2=false},
        {text: '去设置', disabled: btnDisabled, style: 'color:#00e0a1;', click: handleBtnDisabled},
    ]}
>
</Popup>

<!-- Android样式3 -->
<Popup bind:open={showAndroid3} type="androidSheet" zIndex="1111"
    btns={[
        {text: '添加备注', style: 'color:#00e0a1;', click: handleInfo},
        {text: '设置分组', disabled: true,},
        {text: '删除', style: 'color:#e63d23;', click: () => showAndroid3=false},
    ]}
>
</Popup>

svelte自定义弹窗组件

参数配置

代码语言:javascript
复制
<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>

模板语法及逻辑处理。

代码语言:javascript
复制
<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>

/**
 * @Desc     svelte自定义移动端弹窗组件
 * @Time     andy by 2022/3/15
 * @About    Q:282310962  wx:xy190310
 */
<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>

官网有介绍可以通过new一个componnet来实现挂载组件至body上。

const component =newComponent(options)

代码语言:javascript
复制
import App from './App.svelte';

const app = new App({
    target: document.body,
    props: {
        // assuming App.svelte contains something like
        // `export let answer`:
        answer: 42
    }
});
代码语言:javascript
复制
import Popup from './Popup.svelte'

let uuid = function() {
    return 'svpopup-' + Math.floor(Math.random() * 10000)
}

export function svPopup(options = {}) {
    options.id = uuid()

    const mountNode = document.createElement('div')
    document.body.appendChild(mountNode)

    const app = new Popup({
        target: mountNode,
        props: {
            ...options,
            open: true,
            // 传入函数移除指令
            remove() {
                document.body.removeChild(mountNode)
            }
        }
    })
    return app
}

export default Popup

这样就能导出组件和函数方式了。

ok,基于svelte.js开发自定义组件就先分享到这里。后续还会分享一些svelte实例。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 快速引入
  • svelte自定义弹窗组件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档