Svelte3.x網頁聊天例項|svelte.js仿微信PC版聊天svelte-webchat

xiaoyan2017發表於2022-05-15

基於Svelte3+SvelteKit+Sass仿微信Mac介面聊天實戰專案SvelteWebChat

基於svelte3+svelteKit+sass+mescroll.js+svelte-layer+svelte-scrollbar等技術搭建仿微信網頁版聊天案例Svelte-Webchat。全新的Dock選單(可拖拽排序/滑鼠滾輪左右滾動),整體MacOs風格毛玻璃背景虛化效果。

一、使用技術

  • 編輯器:Vscode
  • 框架技術:Svelte^3.46.5+SvelteKit
  • 狀態管理:svelte/store
  • 下拉重新整理:mescroll.js
  • 滾動條元件:svelte-scrollbar
  • 對話方塊元件:svelte-layer
  • sass預處理:sass^1.50.1+svelte-preprocess
  • iconfont圖示:阿里巴巴字型圖示庫

svelte-webchat:支援傳送訊息+emoj表情、圖片/視訊檢視、連結預覽、貼上截圖傳送圖片、紅包/朋友圈、全屏/主題換膚等功能。

二、專案層級結構

◆ 效果預覽

◆ svelte.config.js配置檔案

svelte專案配置檔案,可配置alias別名路徑、sass預編譯等功能。

import adapter from '@sveltejs/adapter-auto'
import path from 'path'
import SvelteProcess from 'svelte-preprocess'

/** @type {import('@sveltejs/kit').Config} */
const config = {
    kit: {
        adapter: adapter(),
        vite: {
            resolve: {
                alias: {
                    '@': path.resolve('./src'),
                    '@assets': path.resolve('./src/assets'),
                    '@utils': path.resolve('./src/utils')
                }
            }
        }
    },
    // 禁用 Svelte 警告 未使用的 CSS 選擇器(css-unused-selector)
    onwarn: (warning, handler) => {
        const { code, frame } = warning
        if (code === "css-unused-selector")
            return
        handler(warning)
    },
    preprocess: SvelteProcess()
};

export default config;

◆ svelte公共模板及錯誤頁

vue.js中有router-view路由管理頁面。svelteKit提供了 __layout.svelte 佈局模板和 __error.svelte 錯誤處理模板。

<div class="sv__container flexbox flex-alignc flex-justifyc" style="--themeSkin: {$skin}">
    <div class="sv__wrapper" class:maximize={$isWinMaximize}>
        {#if $userinfo}
        <div class="sv__board flexbox flex-col">
            <!-- <div class="sv__topbar">頂部模組</div> -->
            <div class="sv__mainwrap flex1 flexbox">
                <!-- <div class="sv__sidebar">側邊欄</div> -->
                <Middle />
                <div class="sv__mainbx flex1 flexbox flex-col">
                    <Winbar />
                    <slot />
                </div>
            </div>
            <Dock />
        </div>
        {:else}
        <div class="sv__board flexbox flex-col">
            <div class="sv__mainwrap flex1 flexbox">
                <slot />
            </div>
        </div>
        {/if}
    </div>
</div>

<script context="module">
    export function load({ error, status }) {
        return {
            props: { error, status }
        }
    }
</script>

<script>
    import { goto } from '$app/navigation'
    export let status
    export let error

    function goBack() {
        // history.go(-1)
        goto('/')
    }
</script>

<svelte:head>
    <title>{status} Error!</title>
</svelte:head>

<div class="sv__scrollview flex1">
    <div class="sv__page-error flexbox flex-col flex-alignc flex-justifyc">
        <div class="sv__page-error-img">
            <img src="404.png" alt="" />
        </div>
        <div class="sv__page-error-content">
            <div class="c-red fs-18">┗| {status} |┛  Page Error~~</div>
            <div class="c-999 mt-10">{error.message}</div>
            <div class="sv__btn sv__btn-default" on:click={goBack}><i class="iconfont icon-arrL"></i> 返回首頁</div>
        </div>
    </div>
</div>

◆ svelte3.x自定義PC彈窗元件

為了專案UI效果整體一致性,所有彈窗功能均是基於svelte.js自定義svelte-layer對話方塊元件實現效果。

對於svelteLayer元件,之前有過一篇分享文章,感興趣的可以去看下。

https://www.cnblogs.com/xiaoyan2017/p/16158044.html

◆ svelte3.x自定義虛擬美化滾動條元件

為了替代系統原生滾動條,於是基於svelte.js開發了一款網頁模擬系統美化滾動條svelte-scrollbar元件。

svelteScrollBar 支援自定義滾動條尺寸/顏色/間距、垂直/水平滾動、自動隱藏、動態DOM監測等功能。

https://www.cnblogs.com/xiaoyan2017/p/16240547.html

◆ svelte自定義Dock選單

如上圖:底部dock選單結合Svelte-Scrollbar元件實現左右滾動(支援滑鼠mousewheel滾輪滑動)

<div class="sv__dockbar flexbox flex-justifyc">
    <div class="sv__dock-scroll" style="background: {bgcolor};">
        <Scrollbar autohide size={2} mousewheel>
            <div class="sv__dock-wrap" bind:this={dockEl}>
                <!-- dock選單項 -->
                {#each menu as item,index}
                    {#if item.type == 'divider'}
                        <div class="sv__dock-divider"></div>
                    {:else}
                        <div class="sv__dock-item flexbox" class:cur={currentTabIndex == index} on:click={changeTab(index, item)}>
                            {#if item.icon}<span class="iconfont {item.icon}" style="color: {item.color}; font-size: {item.iconSize}"></span>{/if}
                            {#if item.img}<img class="iconimg" src={item.img} alt="" style="font-size: {item.iconSize};" />{/if}
                            {#if item.badge}<span class="sv__badge sv__dock-badge">{item.badge}</span>{/if}
                            {#if item.dot}<span class="sv__badge-dot sv__dock-badgeDot"></span>{/if}
                        </div>
                    {/if}
                {/each}
            </div>
        </Scrollbar>
    </div>
</div>

◆ svelte.js表單驗證

svelte3中實現登入表單及獲取驗證碼60s倒數計時功能。

<script>
    import { onMount } from 'svelte'
    import { goto } from '$app/navigation'
    import Layer, { svLayer } from '$lib/Layer'
    import { userinfo } from '@/store'
    import util from '@/utils'

    let formObj = {}
    let vcodeText = '獲取驗證碼'
    let disabled = false
    let time = 0

    let agree = false
    let vcodeLG = true

    let telEl
    onMount(() => {
        userinfo.useStorage()
        telEl.focus()
    })

    function Message(content) {
        svLayer.message({content, icon: 'warning', time: 0, xclose: true, shade: true})
    }

    // 60s倒數計時
    function getVcode() {
        let { tel } = formObj
        if(!tel) {
            Message('手機號不能為空')
        }else if(!util.checkTel(tel)) {
            Message('手機號不正確')
        }else {
            time = 60
            disabled = true
            countDown()
        }
    }
    function countDown() {
        if(time > 0) {
            vcodeText = '獲取驗證碼('+ time +')'
            time--
            setTimeout(countDown, 1000)
        }else {
            vcodeText = '獲取驗證碼'
            time = 0
            disabled = false
        }
    }
    
    function handleSubmit() {
        console.log('——+——+——表單資料:', formObj)

        let { tel, vcode, pwd } = formObj
        if(!tel) {
            Message('手機號不能為空')
        }else if(!util.checkTel(tel)) {
            Message('手機號不正確')
        }else if(vcodeLG && !vcode) {
            Message('驗證碼不能為空')
        }else if(!vcodeLG && !pwd) {
            Message('密碼不能為空')
        }else {
            svLayer({
                type: 'toast',
                icon: 'success',
                content: '登入成功',
                shadeClose: false,
                time: 2,
                onClose: () => {
                    userinfo.set({
                        user: tel,
                        token: util.setToken()
                    })
                    goto('/')
                }
            })
        }
    }
</script>

◆ svelte聊天功能模組

聊天編輯框限制最大高度、支援多行文字+emoj混排、游標處插入內容、貼上/拖拽傳送圖片。

其中表情彈窗是基於svelte-layer實現效果。

<!-- 表情彈窗 -->
<Layer 
    bind:open={isVisibleOpenFace}
    anim="fadeIn"
    type="popover"
    follow="#popover_face"
    placement="top"
    shade="false"
    area="475px"
>
    <!-- 表情 -->
    <div class="vui__emotion" on:click|stopPropagation={()=>null}>
        <div class="vui__emotion-tabs flexbox">
            {#each emojList as item,index}
            <div class="item" class:on={item.selected} on:click={()=>handleEmojTab(index)}><img src={item.pathLabel} alt="" /></div>
            {/each}
            <div class="more flex1"></div>
        </div>
        <div class="vui__emotion-wrap">
            <Scrollbar gap={2} size={2}>
                {#each emojList as item,index}
                <div class="vui__emotion-cells" class:cur={item.selected}>
                    <div class="{item.type == 'emoj' ? 'face__sm_list' : 'face__lg_list'}">
                        {#each item.nodes as item2}
                        <div class="item">
                            {#if item.type=='emoj'}
                            <img src={item2} class="emoj" on:click={handleEmojClicked} alt="" />
                            {:else}
                            <img src={item2} on:click={()=>handleGifClicked(item2)} alt="" />
                            {/if}
                        </div>
                        {/each}
                    </div>
                </div>
                {/each}
            </Scrollbar>
        </div>
    </div>
</Layer>

<!-- 視訊預覽模板 -->
<Layer bind:open={isVisibleVideoPopup}
    title="<span style='color:#aaa;'>視訊預覽<span>"
    opacity=".9"
    area={['360px', '450px']}
    xclose
    xcolor="#aaa"
    maximize
    resize
    layerStyle="background: #333;"
>
    <div class="flex-c" style="background:#333;height: 100%;">
        <!-- //視訊video -->
        {#if isVisibleVideoPopup}
        <video 
            bind:this={videoEl}
            src={videoData.videosrc} 
            autoplay 
            controls
            x5-video-player-fullscreen="true"
            webkit-playsinline="true"
            x-webkit-airplay="true"
            playsinline="true"
            x5-playsinline 
            style="height:100%;width:100%;object-fit:contain;outline:none;"
        />
        {/if}
    </div>
</Layer>

Okay,以上就是svelte.js開發網頁版聊天例項的一些分享。希望對大家有所幫助哈~✍?

最後附上一個uniapp+uview手機端後臺管理系統

https://www.cnblogs.com/xiaoyan2017/p/15836112.html

 

相關文章