• Svelte3.x网页聊天实例|svelte.js仿微信PC版聊天svelte-webchat


    基于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

     

  • 相关阅读:
    NIO基础知识
    AI赋能目标跟踪 智算加速“视”不可挡
    Matlab数学建模常用函数
    Vue:(五)事件初探
    世界上第一台个人电脑是哪台?
    支持流畅运行win10的最低配置是什么
    国内访问Github超级慢?那是你没有用我这个脚本。直接起飞。
    【收获合辑】k-NN与检索任务的异同+jupyter转pdf
    TOGAF标准第10版读书会第14场—加速数字化政府建设,离不开这个参考指导模型
    不用addEventListener(‘resize‘, this.resize),用新的Web API ResizeObserver监听DIV元素尺寸的变化
  • 原文地址:https://www.cnblogs.com/xiaoyan2017/p/16272097.html