Svelte+Sass+Mescroll.js仿微信app聊天实例

2022-04-10 09:21:51 浏览数 (1)

项目介绍

svelte3-chat 基于svelte.js svelteKit Sass开发的仿微信界面聊天实战项目。

svelte.js 一个运行速度快、无虚拟dom的前端新框架。语法比vue还简单,上手快。

svelteChat 支持富文本消息、网址/图片/视频预览、红包、朋友圈等功能。

使用技术

  • 编辑器:vscode
  • 框架技术:svelte^3.46.0 svelteKit
  • 下拉组件:mescroll.js^1.4.2
  • 样式处理:sass svelte-preprocess
  • 弹窗组件:svelte-popup

目录结构

基于svelte.js和svelteKit构建的项目,目录结构如下:

共用模板

在routes目录下新建一个__layout.svelte布局公共模板。

代码语言:javascript复制
<script>
    import { onMount } from 'svelte'
    import { page } from '$app/stores'
    import { goto } from '$app/navigation'
    import { userinfo } from '@/store/index.js'

    let whiteRoute = ['/auth/login', '/auth/register']

    onMount(() => {
        if(!$userinfo) {
            goto('/auth/login')
        }else {
            if(whiteRoute.includes($page.url.pathname)) {
                goto('/')
            }else {
                goto($page.url.pathname)
            }
        }
    })
</script>

<div class="sv__container flexbox flex-col">
    <slot />
</div>

<style>
    @import '@/app.scss';
    @import '@assets/css/reset.scss';
    @import '@assets/css/layout.scss';
    @import '@assets/fonts/iconfont.css';
</style>

svelte.config.js配置

在svelte项目中也可以使用sass来编写样式。需要安装如下依赖。

代码语言:javascript复制
npm i sass svelte-preprocess -S
代码语言:javascript复制
/**
 * svelte.config.js基础配置文件
 */

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')
                }
            }
        }
    },
    // allow you to use Svelte with tools like TypeScript, PostCSS, SCSS, and Less.
    preprocess: SvelteProcess()
};

export default config

svelte3自定义组件

项目中顶部导航条navbar、底部菜单栏tabbar及弹窗组件svelte-popup 均是基于svelte自定义组件实现功能。

svelte.js自定义顶部导航栏 菜单栏组件

svelte3自定义多功能手机端弹窗组件sveltePopup

svelte.js状态管理

svelte也提供了状态管理工具svelte/store,可做一些简单的封装。

代码语言:javascript复制
/**
 * Svelte状态管理
*/

import { writable } from 'svelte/store'

const createStore = (value, key) => {
    const { subscribe, set, update } = writable(value)
    return {
        // 持久化存储
        useStorage: () => {
            const data = localStorage.getItem(key)
            if(data) {
                set(JSON.parse(data))
            }
            // 订阅
            subscribe(val => {
                [null, undefined].includes(val) ? localStorage.removeItem(key) : localStorage.setItem(key, JSON.stringify(val))
            })
        },
        subscribe,
        set,
        update,
    }
}

export const userinfo = createStore(localStorage.getItem('userinfo')||null, 'userinfo')

svelte.js实现聊天功能

editor.svelte 聊天文本框支持文字 emoj混排,多行文本、光标处插入表情、网址/图片/视频预览、红包等功能。

代码语言:javascript复制
<script>
    // 编辑器
    export let editor

    import { tick, createEventDispatcher } from 'svelte'
    const dispatch = createEventDispatcher()

    let editorNode
    let lastCursor = null

    // 获取光标最后位置
    function getLastCursor() {
        let sel = window.getSelection()
        if(sel && sel.rangeCount > 0) {
            return sel.getRangeAt(0)
        }
    }

    // 光标位置插入内容
    export async function addHtmlInCursor(html) {
        // ...
    }

    // 删除编辑器内容
    export async function deleteHtml() {
        let range
        let sel = window.getSelection()
        if(lastCursor) {
            sel.removeAllRanges()
            sel.addRange(lastCursor)
        }
        range = getLastCursor()
        range.collapse(false)
        document.execCommand('delete')

        await tick()
        editorNode.blur()
    }

    function handleInput() {
        editor = editorNode.innerHTML
        lastCursor = getLastCursor()
    }

    function handleClick() {
        dispatch('click')
        lastCursor = getLastCursor()
    }

    function handleFocus() {
        dispatch('focus')
        lastCursor = getLastCursor()
    }

    function handleBlur() {
        dispatch('blur')
    }
</script>

<div
    class="editor"
    bind:this={editorNode}
    contenteditable="true"
    bind:innerHTML={editor}
    on:input={handleInput}
    on:click={handleClick}
    on:focus={handleFocus}
    on:blur={handleBlur}
    style="user-select: text; -webkit-user-select: text;"
></div>

好了,今天就先分享这么多。后续还会分享一些实例项目。

0 人点赞