svelte組件:svelte3自定義桌面PC端對話框組件svelte-layer

来源:https://www.cnblogs.com/xiaoyan2017/archive/2022/04/18/16158044.html
-Advertisement-
Play Games

基於Svelte3.x開發pc網頁版自定義彈窗組件svelteLayer。 svelte-layer:基於svelte.js輕量級多功能pc桌面端對話框組件。支持多種彈窗類型、30+參數隨意組合配置,整合了拖拽/四周縮放/最大化/記憶彈窗位置/全屏/自定義層級等功能。 svelteLayer功能效果 ...


基於Svelte3.x開發pc網頁版自定義彈窗組件svelteLayer

svelte-layer:基於svelte.js輕量級多功能pc桌面端對話框組件。支持多種彈窗類型、30+參數隨意組合配置,整合了拖拽/四周縮放/最大化/記憶彈窗位置/全屏/自定義層級等功能。

svelteLayer功能效果上有些類似layer.js插件。

◆ 快速引入

在需要使用組件功能的頁面,引入組件。

import Layer, {svLayer} from '$lib/Layer'

svelteLayer支持標簽式+函數式兩種調用方式。

  • 標簽式調用
<!-- 詢問框 -->
<Layer bind:open={showConfirm} shadeClose="false" title="警告信息" xclose zIndex="2001" lockScroll={false} resize dragOut
    content="<div style='color:#00e0a1;padding:20px 40px;'>這裡是確認框提示信息</div>"
    btns={[
        {text: '取消', click: () => showConfirm=false},
        {text: '確定', style: 'color:#e63d23;', click: handleInfo},
    ]}
/>
  • 函數式調用
function handleInfo(e) {
    let el = svLayer({
        title: '標題',
        content: `<div style="padding:20px;">
            <p>函數式調用:<em style="color:#999;">svLayer({...})</em></p>
        </div>`,
        resize: true,
        btns: [
            {
                text: '取消',
                click: () => {
                    // 關閉彈窗
                    el.$set({open: false})
                }
            },
            {
                text: '確認',
                style: 'color:#09f;',
                click: () => {
                    svLayer({
                        type: 'toast',
                        icon: 'loading',
                        content: '載入中...',
                        opacity: .2,
                        time: 2
                    })
                }
            },
        ]
    })
}

支持標簽式和函數式混合搭配調用,還支持如上圖動態載入外部組件。

◆ 參數配置

svelte-layer預設支持如下參數自定義配置。

<script context="module">
    let index = 0 // 用於控制倒計時臨時索引
    let lockNum = 0 // 用於控制鎖定屏幕臨時索引
</script>

<script>
    // 是否打開彈窗bind:open={showDialog}
    export let open = false
    // 彈窗標識
    export let id = undefined
    // 標題
    export let title = ''
    // 內容
    export let content = ''
    // 彈窗類型
    export let type = ''
    // 自定義樣式
    export let layerStyle = undefined
    // 自定義類名
    export let customClass = ''
    // toast圖標
    export let icon = ''
    // 是否顯示遮罩層
    export let shade = true
    // 點擊遮罩層關閉
    export let shadeClose = true
    // 鎖定屏幕
    export let lockScroll = true
    // 遮罩層透明度
    export let opacity = ''
    // 是否顯示關閉圖標
    export let xclose = false
    // 關閉圖標位置
    export let xposition = 'right'
    // 關閉圖標顏色
    export let xcolor = '#000'
    // 彈窗動畫
    export let anim = 'scaleIn'
    // 彈出位置(auto | ['100px','50px'] | t | r | b | l | lt | rt | lb | rb)
    export let position = 'auto'
    // 抽屜彈窗
    export let drawer = ''
    // 右鍵彈窗定位
    export let follow = null
    // 彈窗自動關閉時間
    export let time = 0
    // 彈窗層級
    export let zIndex = 202204
    // 置頂彈窗
    export let topmost = false
    // 彈窗大小
    export let area = 'auto'
    // 彈窗最大寬度
    export let maxWidth = 375
    // 彈窗是否最大化
    export let maximize = false
    // 彈窗是否全屏
    export let fullscreen = false
    // 是否固定
    export let fixed = true
    // 是否拖拽
    export let drag = '.vlayer__wrap-tit'
    // 是否拖拽屏幕外
    export let dragOut = false
    // 限制拖拽方向 vertical|horizontal
    export let dragDir = ''
    // 拖拽結束回調 {width: 120, height: 120, x: 100, y: 100}
    export let dragEnd = undefined
    // 是否縮放
    export let resize = false

    // 彈窗按鈕事件
    export let btns = null
    /*export let btns = [
        {text: '取消', style: 'color:red', disabled: true, click: null},
        {text: '確定', style: 'color:blue', click: null}
    ]*/

    // 函數式打開|關閉回調
    export let onOpen = undefined
    export let onClose = undefined
    export let beforeClose = undefined

    // 接收函數移除指令
    export let remove = undefined

    import { onMount, afterUpdate, createEventDispatcher, tick } from 'svelte'
    const dispatch = createEventDispatcher()
    
    // ...
</script>

彈窗模板及核心邏輯處理。

<div class="vui__layer" class:opened class:vui__layer-closed={closeCls} id={id} bind:this={el}>
    <!-- 遮罩層 -->
    {#if bool(shade)}<div class="vlayer__overlay" on:click={shadeClicked} style:opacity></div>{/if}
    <!-- 主體 -->
    <div class="vlayer__wrap {type&&'popui__'+type} anim-{anim}" style="{layerStyle}">
        {#if title}<div class="vlayer__wrap-tit">{@html title}</div>{/if}
        {#if icon&&type=='toast'}<div class="vlayer__toast-icon vlayer__toast-{icon}">{@html toastIcon[icon]}</div>{/if}
        <div class="vlayer__wrap-cntbox">
            <!-- 判斷content插槽是否存在 -->
            {#if $$slots.content}
                <div class="vlayer__wrap-cnt"><slot name="content" /></div>
            {:else}
                {#if content}
                    <!-- iframe -->
                    {#if type=='iframe'}
                    <div class="vlayer__wrap-iframe">
                        <iframe scrolling="auto" allowtransparency="true" frameborder="0" src={content}></iframe>
                    </div>
                    <!-- message|notify|popover -->
                    {:else if type=='message' || type=='notify' || type=='popover'}
                    <div class="vlayer__wrap-cnt">
                        {#if icon}<i class="vlayer-msg__icon {icon}">{@html messageIcon[icon]}</i>{/if}
                        <div class="vlayer-msg__group">
                            {#if title}<div class="vlayer-msg__title">{@html title}</div>{/if}
                            <div class="vlayer-msg__content">{@html content}</div>
                        </div>
                    </div>
                    <!-- 載入動態組件 -->
                    {:else if type == 'component'}
                    <svelte:component this={content}/>
                    {:else}
                    <div class="vlayer__wrap-cnt">{@html content}</div>
                    {/if}
                {/if}
            {/if}
            <slot />
        </div>

        <!-- 按鈕組 -->
        {#if btns}
        <div class="vlayer__wrap-btns">
            {#each btns as btn,index}
                <span class="btn" class:btn-disabled={btn.disabled} style="{btn.style}">{@html btn.text}</span>
            {/each}
        </div>
        {/if}

        {#if xclose}
        <span class="vlayer__xclose" style="color: {xcolor}" on:click={hide}></span>
        {/if}
        {#if maximize}<span class="vlayer__maximize" on:click={maximizeClicked}></span>{/if}
        <!-- 縮放 -->
        {#if resize}
        <span class="vlayer__groupresize">
            <i class="vlayer__resize LT"></i>
            <i class="vlayer__resize RT"></i>
            <i class="vlayer__resize LB"></i>
            <i class="vlayer__resize RB"></i>
        </span>
        {/if}
    </div>
    <!-- 優化拖拽卡頓 -->
    <div class="vlayer__dragfix"></div>
</div>

<script>
    /**
     * @Desc     Svelte.js桌面端對話框組件SvelteLayer
     * @Time     andy by 2022-04
     * @About    Q:282310962  wx:xy190310
     */
    
    // ...

    onMount(() => {
        console.log('監聽彈窗開啟')
        window.addEventListener('resize', autopos, false)
        return () => {
            console.log('監聽彈窗關閉')
            window.removeEventListener('resize', autopos, false)
        }
    })

    afterUpdate(() => {
        console.log('監聽彈窗更新')
    })

    // 動態監聽開啟/關閉
    $: if(open) {
        show()
    }else {
        hide()
    }

    /**
     * 開啟彈窗
     */
    async function show() {
        if(opened) return
        opened = true
        dispatch('open')
        typeof onOpen === 'function' && onOpen()

        // 避免獲取彈窗寬高不准確
        await tick()

        zIndex = util.getZIndex(zIndex) + 1

        auto()
    }

    /**
     * 關閉彈窗
     */
    function hide() {
        // ...
    }

    // 彈窗位置
    function auto() {
        autopos()

        // 全屏彈窗
        if(fullscreen) {
            full()
        }

        // 拖拽|縮放
        move()
    }

    // 彈窗定位
    function autopos() {
        if(!opened) return
        let ol, ot
        let pos = position
        let isfixed = bool(fixed)
        let vlayero = el.querySelector('.vlayer__wrap')

        if(!isfixed || follow) {
            vlayero.style.position = 'absolute'
        }

        let area = [util.client('width'), util.client('height'), vlayero.offsetWidth, vlayero.offsetHeight]

        ol = (area[0] - area[2]) / 2
        ot = (area[1] - area[3]) / 2

        if(follow) {
            offset()
        }else {
            typeof pos === 'object' ? (
                ol = parseFloat(pos[0]) || 0, ot = parseFloat(pos[1]) || 0
            ) : (
                pos == 't' ? ot = 0 : 
                pos == 'r' ? ol = area[0] - area[2] : 
                pos == 'b' ? ot = area[1] - area[3] : 
                pos == 'l' ? ol = 0 : 
                pos == 'lt' ? (ol = 0, ot = 0) : 
                pos == 'rt' ? (ol = area[0] - area[2], ot = 0) : 
                pos == 'lb' ? (ol = 0, ot = area[1] - area[3]) :
                pos == 'rb' ? (ol = area[0] - area[2], ot = area[1] - area[3]) : 
                null
            )

            vlayero.style.left = parseFloat(isfixed ? ol : util.scroll('left') + ol) + 'px'
            vlayero.style.top = parseFloat(isfixed ? ot : util.scroll('top') + ot) + 'px'
        }
    }

    // 跟隨定位
    function offset() {
        let ow, oh, ps
        let vlayero = el.querySelector('.vlayer__wrap')

        ow = vlayero.offsetWidth
        oh = vlayero.offsetHeight
        ps = util.getFollowRect(follow, ow, oh)
        tipArrow = ps[2]

        vlayero.style.left = ps[0] + 'px'
        vlayero.style.top = ps[1] + 'px'
    }

    	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在上一篇中我們簡單總結和介紹了Redis的幾個方面 1.使用Redis背景 2.Redis通信多路復用的基本原理 3.Redis基本數據結構 4.Redis持久化方式 這一篇我們使用簡單的業務場景來介紹Redis的分散式鎖和集群 1.分散式鎖 首先我們應該知道什麼是分散式鎖,用來做什麼的,解決了什麼 ...
  • 安裝軟體 pacman -S (軟體名):安裝軟體,若有多個軟體包,空格分隔 pacman -S --needed (軟體名):安裝軟體,若存在,不重新安裝最新的軟體 pacman -Sy (軟體名):安裝軟體前,先從遠程倉庫下載軟體包資料庫 pacman -Sv (軟體名):輸出操作信息後安裝 p ...
  • Linux 筆記 基本概念 UNIX 體繫結構 操作系統(內核):一種軟體,控制電腦硬體資源,提供程式運行環境。 ​ 內核的介面被稱為系統調用 (system call, 圖中的陰影部分)。公用函數庫構建在系統調用介面之上,應用程式既可使用公用函數庫,也可使用系統調用。(我們將在 1.11節對系統 ...
  • 【Linux篇】kali Linux下的su、sudo命令用法說明 ​ 總結一下su、sudo命令用法區別 【suy】 1、實驗環境 系統 版本 Windows11專業版 版本:21H2(OS內部版本 22000.613); kali Linux 版本:4.4.0-22593; (一)【su】Swi ...
  • 重溫51彙編指令(附實驗) 寫在前面: 在電子控制的課上,老師帶我們重溫了一些51的彙編指令,有了一些新的思考,感覺非常的有趣,所以這裡進行總結和嘗試。 正文: 實驗平臺: keil5 實驗目標MCU: intel的80C51BH 51寄存器的簡單介紹: 通過debug視窗可以進行觀察 符號以及寄存 ...
  • 手工釋放Linux Cache Memory 為了加速操作和減少磁碟I/O,內核通常會儘可能多地緩存記憶體,這部分記憶體就是Cache Memory(緩存記憶體)。根據設計,包含緩存數據的頁面可以按需重新用於其他用途(例如,應用程式)。 緩存記憶體在程式運行結束後不會自動釋放。這可能會導致程式頻繁讀寫文件後 ...
  • TL;NRs 初始化服務時最好使用mysqld --initialized --console命令; MySQL8.0的配置變數與MySQL5.7不同,[mysqld]下麵設置字元集的變數名為character_set_server; 修改密碼的命令為alter user 'root'@'local ...
  • MySQL8自增主鍵變化 醉後不知天在水,滿船清夢壓星河。 一、簡述 MySQL版本從5直接大躍進到8,相信MySQL8一定會有很多令人意想不到的改進,如果不想只會CRUD可以看看。 比如系統表引擎的變化-全部換成事務型的InnoDB。 MySQL5.7系統部引擎 MySQL8系統引擎 上圖可以看到 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...