概述
Svelte-Webchat 一款仿造微信网页版类Mac界面聊天我的项目。应用最新技术栈svelte3.x+svelteKit+sass+mescroll+svelte-layer
等技术开发构建。别致的dock可拖拽/左右滚动菜单。
性能特效
✅经典Dock可滚动菜单模式
✅晦涩的操作体验
✅可膨胀/开展侧边
✅可全屏/复原窗口、退出弹窗提醒
✅丰盛的视觉效果,自定义桌面虚化主题
✅自定义可视化弹窗+滚动条,反对各种自定义定制开发。
技术栈
- 编辑器:Vscode
- 框架技术:Svelte^3.46.5+SvelteKit
- 状态治理:svelte/store
- 下拉刷新:mescroll.js
- 滚动条组件:svelte-scrollbar
- 对话框组件:svelte-layer
- sass预处理:sass^1.50.1+svelte-preprocess
svelte-webchat 还内置了朋友圈模块。
我的项目构造
十分清晰的分层目录构造。
svelte自定义组件(弹窗+滚动条)
我的项目中无处不在的弹窗及滚动条性能,均是基于svelte.js自定义组件实现性能。
- svelte-layer 一款基于svelte3开发的网页对话框组件
https://segmentfault.com/a/1190000041721778 - svelte-scrollbar 一款基于svelte.js虚构丑化滚动条组件
https://segmentfault.com/a/1190000041814107
因为之前有过相干分享文章,这里就不具体的介绍了。
svelte公共布局模板
svelteKit提供了__layout.svelte
布局模板及__error.svelte
错误处理页面。
如上图:整体布局分为左侧+右侧内容区+底部dock菜单。
<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" style="color:#40b3ff;height:32px;width:120px;" on:click={goBack}><i class="iconfont icon-arrL"></i> 返回首页</div> </div> </div></div>
svelte实现聊天
聊天编辑框反对多行文本、光标处插入内容,粘贴截图发送图片+拖拽发送图片。
编辑框监听paste事件
editorEl.addEventListener('paste', function(e) { e.preventDefault() let cbd = e.clipboardData let ua = window.navigator.userAgent if(!(e.clipboardData && e.clipboardData.items)) return if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" && cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" && ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){ return; } for(var i = 0; i < cbd.items.length; i++) { var item = cbd.items[i] // console.log(item) // console.log(item.kind) if(item.kind == 'file') { var blob = item.getAsFile() if(blob.size === 0) return // 读取图片记录 var reader = new FileReader() reader.readAsDataURL(blob) reader.onload = function() { var imgpath = this.result // 返回图片给父组件 dispatch('paste', imgpath) } } }})
svelte拖拽上传
/** * svelte拖拽上传图片 * author:andy Q:282310962 */function handleDragEnter(e) { e.stopPropagation() e.preventDefault()}function handleDragOver(e) { e.stopPropagation() e.preventDefault()}function handleDrop(e) { e.stopPropagation() e.preventDefault() handleFileList(e.dataTransfer)}// 拖拽文件列表function handleFileList(filelist) { let files = filelist.files if(files.length >= 2) { svLayer.message({content: '临时反对拖拽一张图片', icon: 'error', time: 0, xclose: true, shade: true}) return false } for(let i = 0; i < files.length; i++) { if(files[i].type != '') { handleFileAdd(files[i]) }else { svLayer.message({content: '目前不反对文件夹拖拽性能', icon: 'error', time: 0, xclose: true, shade: true}) } }}function handleFileAdd(file) { let len = msgList.length // 音讯队列 let msgArr = { id: `msg_${++len}`, msgtype: 5, isme: true, avatar: '/uimg/img-avatar08.jpg', author: 'Hison', msg: '', imgsrc: '', videosrc: '' } if(file.type.indexOf('image') == -1) { svLayer.message({content: '目前不反对非图片拖拽性能', icon: 'error', time: 0, xclose: true, shade: true}) }else { let reader = new FileReader() reader.readAsDataURL(file) reader.onload = async function() { let img = this.result msgArr.imgsrc = img msgList = msgList.concat(msgArr) await tick() scrollBottom() } }}
OK,基于svelte.js开发仿微信web版聊天实例就分享到这里。
最初附上两个最新实例我的项目
https://segmentfault.com/a/1190000041357547
https://segmentfault.com/a/1190000040015181