概述
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