基于react18+react-vant+zustand仿微信手机端聊天室ReactChat

react18-chat 一款使用最新react18.x hooks、zustand搭配react-vant组件库开发的mobile版仿微信界面聊天实例项目。实现了发送图文消息、图片/视频预览、红包/朋友圈等功能。

技术栈

  • 编辑器:vscode
  • 框架技术:react18+react-dom+react-router-dom+vite4.x
  • UI组件库:react-vant (有赞react移动端UI库)
  • 状态管理:zustand^4.3.9
  • 路由管理:react-router-dom^6.14.2
  • className混合:clsx^2.0.0
  • 弹框组件:rcpop (基于react18 hooks自定义手机端弹框组件)
  • 样式处理:sass^1.64.1

项目结构

使用vscode开发工具,整个项目采用react18 hooks函数组件编码开发。

如果对react18 hooks开发自定义弹框组件感兴趣,可以去看看这篇分享文章。

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

整个项目使用到的弹窗组件均是rcpop自定义弹窗组件实现功能,支持多种弹窗类型/动画效果及20+参数配置。

React18 Hooks自定义导航栏Navbar+菜单栏Tabbar

项目中顶部navbar及底部tabbar组件均是基于react18自定义组件实现功能。

在components目录下新建navbar和tabbar组件目录。

<Navbar
back={false}
bgcolor="linear-gradient(to right, #139fcc, #bc8bfd)"
title={<span className="ff-gg">React18-Chat</span>}
fixed
right={
<>
<i className="iconfont ve-icon-search"></i>
<i className="iconfont ve-icon-plus-circle-o ml-30"></i>
</>
}
/>

<Tabbar bgcolor="#fefefe" onClick={handleTabClick} />

主入口main.jsx

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './style.scss' ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)

主模板App.jsx配置

import { HashRouter } from 'react-router-dom'

// 引入useRoutes集中式路由配置
import Router from './router' // 引入fontSize
import '@assets/js/fontSize' function App() {
return (
<>
<HashRouter>
<Router />
</HashRouter>
</>
)
} export default App

react-router-dom路由管理配置

使用最新版react-router-dom v6进行路由管理。

/**
* react路由配置管理 by YXY Q:282310962
*/ import { lazy, Suspense } from 'react'
import { useRoutes, Outlet, Navigate } from 'react-router-dom'
import { Loading } from 'react-vant' import { authStore } from '@/store/auth' // 引入路由页面
import Login from '@views/auth/login'
import Register from '@views/auth/register'
const Index = lazy(() => import('@views/index'))
const Contact = lazy(() => import('@views/contact'))
const Uinfo = lazy(() => import('@views/contact/uinfo'))
const Chat = lazy(() => import('@views/chat/chat'))
const ChatInfo = lazy(() => import('@views/chat/info'))
const RedPacket = lazy(() => import('@views/chat/redpacket'))
const My = lazy(() => import('@views/my'))
const Fzone = lazy(() => import('@views/my/fzone'))
const Wallet = lazy(() => import('@views/my/wallet'))
const Setting = lazy(() => import('@views/my/setting'))
const Error = lazy(() => import('@views/404')) // 加载提示
const SpinLoading = () => {
return (
<div className="rc__spinLoading">
<Loading size="20" color="#087ea4" vertical textColor="#999">加载中...</Loading>
</div>
)
} // 延迟加载
const lazyload = children => {
// React 16.6 新增了<Suspense>组件,让你可以“等待”目标代码加载,并且可以直接指定一个加载的界面
// 懒加载的模式需要我们给他加上一层 Loading的提示加载组件
return <Suspense fallback={<SpinLoading />}>{children}</Suspense>
} // 路由鉴权验证
const RouterAuth = ({ children }) => {
const authState = authStore() return authState.isLogged ? (
children
) : (
<Navigate to="/login" replace={true} />
)
} // 路由占位模板(类似vue中router-view)
const RouterLayout = () => {
return (
<div className="rc__container flexbox flex-col">
<Outlet />
</div>
)
} // useRoutes集中式路由配置
export const routerConfig = [
{
path: '/',
element: lazyload(<RouterAuth><RouterLayout /></RouterAuth>),
children: [
// 首页
// { path: '/', element: <Index /> },
{ index: true, element: <Index /> }, // 通讯录模块
// { path: '/contact', element: lazyload(<Contact />) },
{ path: '/contact', element: <Contact /> },
{ path: '/uinfo', element: <Uinfo /> }, // 聊天模块
{ path: '/chat', element: <Chat /> },
{ path: '/chatinfo', element: <ChatInfo /> },
{ path: '/redpacket', element: <RedPacket /> }, // 我的模块
{ path: '/my', element: <My /> },
{ path: '/fzone', element: <Fzone /> },
{ path: '/wallet', element: <Wallet /> },
{ path: '/setting', element: <Setting /> }, // 404模块 path="*"不能省略
{ path: '*', element: <Error /> }
]
},
// 登录/注册
{ path: '/login', element: <Login /> },
{ path: '/register', element: <Register /> }
] const Router = () => useRoutes(routerConfig) export default Router

react18状态管理Zustand

以往都是react搭配redux、react-redux进行状态管理,这次则改为使用轻量级zustand,非常灵活小巧的一款react状态管理插件,支持本地持久化存储。使用语法上有些类似vue3状态管理插件Pinia。

/**
* Zustand状态管理,配合persist本地持久化存储
*/
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware' export const authStore = create(
persist(
(set, get) => ({
isLogged: false,
token: null,
loggedData: (data) => set({isLogged: data.isLogged, token: data.token})
}),
{
name: 'authState',
// name: 'auth-store', // name of the item in the storage (must be unique)
// storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
}
)
)
import { authStore } from '@/store/auth'

function auth() {
const authState = authStore()
authState.xxx ...
}

这样会在本地存储有authState记录了。

React-Chat聊天模块功能

聊天编辑框支持在光标处插入表情,多行文本输入等功能。

<div
{...rest}
ref={editorRef}
className={clsx('editor', className)}
contentEditable
onClick={handleClick}
onInput={handleInput}
onFocus={handleFocus}
onBlur={handleBlur}
style={{'userSelect': 'none', 'WebkitUserSelect': 'none'}}
>
</div>

解决了react18 hooks输入框每次输入光标就会跳回到首位的问题。

/**
* 编辑器模板
*/
import { useRef, useState, useEffect, forwardRef, useImperativeHandle } from 'react'
import clsx from 'clsx' const Editor = forwardRef((props, ref) => {
const {
// 编辑器值
value = '', // 事件
onClick = () => {},
onFocus = () => {},
onBlur = () => {},
onChange = () => {}, className,
...rest
} = props const [editorText, setEditorText] = useState(value)
const editorRef = useRef(null) const isChange = useRef(true)
// 记录光标位置
const lastCursor = useRef(null) // 获取光标最后位置
const getLastCursor = () => {
let sel = window.getSelection()
if(sel && sel.rangeCount > 0) {
return sel.getRangeAt(0)
}
} const handleInput = () => {
setEditorText(editorRef.current.innerHTML) lastCursor.current = getLastCursor()
} // 点击编辑器
const handleClick = () => {
onClick?.() lastCursor.current = getLastCursor()
}
// 获取焦点
const handleFocus = () => {
isChange.current = false
onFocus?.() lastCursor.current = getLastCursor()
}
// 失去焦点
const handleBlur = () => {
isChange.current = true
onBlur?.()
} // 删除内容
const handleDel = () => {
let range
let sel = window.getSelection()
if(lastCursor.current) {
sel.removeAllRanges()
sel.addRange(lastCursor.current)
}
range = getLastCursor()
range.collapse(false)
document.execCommand('delete') // 删除表情时禁止输入法
setTimeout(() => { editorRef.current.blur() }, 0);
}
// 清空编辑器
const handleClear = () => {
editorRef.current.innerHTML = ''
} // 光标处插入内容 @param html 需要插入的内容
const insertHtmlAtCursor = (html) => {
let sel, range
if(!editorRef.current.childNodes.length) {
editorRef.current.focus()
} if(window.getSelection) {
// IE9及其它浏览器
sel = window.getSelection() // ##注意:判断最后光标位置
if(lastCursor.current) {
sel.removeAllRanges()
sel.addRange(lastCursor.current)
} if(sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0)
range.deleteContents()
let el = document.createElement('div')
el.appendChild(html)
var frag = document.createDocumentFragment(), node, lastNode
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node)
}
range.insertNode(frag)
if(lastNode) {
range = range.cloneRange()
range.setStartAfter(lastNode)
range.collapse(true)
sel.removeAllRanges()
sel.addRange(range)
}
}
} else if(document.selection && document.selection.type != 'Control') {
// IE < 9
document.selection.createRange().pasteHTML(html)
}
} useEffect(() => {
if(isChange.current) {
setEditorText(value)
}
}, [value]) useEffect(() => {
onChange?.(editorText)
}, [editorText]) // 暴露指定的方法给父组件调用
useImperativeHandle(ref, () => ({
insertHtmlAtCursor,
handleDel,
handleClear
})) return (
...
)
}) export default Editor

OK,以上就是react18 hooks开发移动端聊天室的一些分享,希望对大家有所帮助哈~~

最后附上两个最新实战项目案例

tauri-admin通用后台管理系统:https://www.cnblogs.com/xiaoyan2017/p/17552562.html

uni-chatgpt跨端仿制ChatGPT会话:https://www.cnblogs.com/xiaoyan2017/p/17507581.html

React-Chat移动端聊天实例|react18 hooks仿微信App聊天界面的更多相关文章

  1. Vue3.0聊天室|vue3+vant3仿微信聊天实例|vue3.x仿微信app界面

    一.项目简介 基于Vue3.0+Vant3.x+Vuex4.x+Vue-router4+V3Popup等技术开发实现的仿微信手机App聊天实例项目Vue3-Chatroom.实现了发送图文表情消息/g ...

  2. uniapp+nvue实现仿微信App聊天应用 —— 成功实现好友聊天+语音视频通话功能

    基于uniapp + nvue实现的uniapp仿微信App聊天应用 txim 实例项目,实现了以下功能. 1: 聊天会话管理 2: 好友列表 3: 文字.语音.视频.表情.位置等聊天消息收发 4: ...

  3. 【手把手教程】uniapp + vue 从0搭建仿微信App聊天应用:腾讯云TXIM即时通讯的最佳实践

    基于uniapp + vue 实现仿微信App聊天应用实践,实现以下功能 1: 用户登陆 2: 聊天会话管理 3: 文本/图片/视频/定位消息收发 4: 贴图表情消息收发 5: 一对一语音视频在线通话 ...

  4. Tauri-Vue3桌面端聊天室|tauri+vite3仿微信|tauri聊天程序EXE

    基于tauri+vue3.js+vite3跨桌面端仿微信聊天实例TauriVue3Chat. tauri-chat 运用最新tauri+vue3+vite3+element-plus+v3layer等 ...

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

    基于Svelte3+SvelteKit+Sass仿微信Mac界面聊天实战项目SvelteWebChat. 基于svelte3+svelteKit+sass+mescroll.js+svelte-lay ...

  6. Svelte3聊天室|svelte+svelteKit仿微信聊天实例|svelte.js开发App

    基于svelte3.x+svelteKit构建仿微信App聊天应用svelte-chatroom. svelte-chatroom 基于svelte.js+svelteKit+mescroll.js+ ...

  7. uniapp+nvue实现仿微信App界面+功能 —— uni-app实现聊天+语音+视频+图片消息

    基于uniapp + nvue实现的uniapp仿微信界面功能聊天应用 txim 实例项目,实现了以下功能. 1: 聊天会话管理 2: 好友列表 3: 文字.语音.视频.表情.位置等聊天消息收发 4: ...

  8. electron聊天室|vue+electron-vue仿微信客户端|electron桌面聊天

    一.项目概况 基于Electron+vue+electron-vue+vuex+Nodejs+vueVideoPlayer+electron-builder等技术仿制微信电脑端界面聊天室实例,实现消息 ...

  9. uni-app聊天室|vue+uniapp仿微信聊天实例|uniapp仿微信App界面

    一.介绍 运用UniApp+Vue+Vuex+swiper+uniPop等技术开发的仿微信原生App聊天室|仿微信聊天界面实例项目uniapp-chatroom,实现了发送图文消息.表情(gif图), ...

  10. Nuxt+Vue聊天室|nuxt仿微信App界面|nuxt.js聊天实例

    一.项目简述 nuxt-chatroom 基于Nuxt.js+Vue.js+Vuex+Vant+VPopup等技术构建开发的仿微信|探探App界面社交聊天室项目.实现了卡片式翻牌滑动.消息发送/emo ...

随机推荐

  1. 使用 MRKL 系统跨越神经符号鸿沟

    本文展示了自然语言处理的下一步发展--模块化推理.知识和语言( the Modular Reasoning, Knowledge and Language,简称为MRKL)系统以及LangChain和 ...

  2. Requested setting LOGGING_CONFIG, but settings are not configured

  3. PTA L1-064 估值一亿的AI核心代码

    PTA L1-064 估值一亿的AI核心代码 有坑!不少 题目链接 题目及分析 题目: 本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:       1. 无论用户说什么,首先把对方说 ...

  4. python 环境下使用PIP 报错的解决方法

    最近做一个小程序项目,使用djangorestframework,安装restframework 出现错误,安装环境Python2.7:出现错误如下:  "UnicodeEncodeErro ...

  5. Java(循环语句,数组)

    Java循环 1.while while( 表达式 ) { //循环内容 } 2.do while do { //循环内容 }while(表达式); 3.for for(初始化; 表达式; 更新) { ...

  6. 如何安装旧版本的 R 包

    由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文中链接. 我们在安装 R 包的时候,经常会发现某个最新的包与当前 R 的版本不兼容. > inst ...

  7. 使用Mybatis-Plus问题解答

    我们使用一个新的框架难免会遇到各种问题,当然使用这款国产的优秀的Mybatis-Plus框架也不例外,下面我就给大家列举一下使用Mybatis-Plus可能遇到的一些问题,并做一下一一的解答. 1:如 ...

  8. 大家听过Java applet吗?为什么不再流行了

    前言 Java applet 不知道有同学听过吗?我也只是听过,并没有使用过.我特意去了解了一下它,本文就对 Java applet 进行简单介绍,说说它的辉煌与衰败.仅此而已,现在已经没人使用 Ja ...

  9. Framework 中使用 Toolkit.Mvvm 的生成器功能

    .NET Standard是.NET APIs的正式规范,可在多个.NET实现中使用..NET Standard的动机是为了在.NET生态系统中建立更大的统一性..NET 5及更高版本采用了不同的方法 ...

  10. CF1817C Similar Polynomials

    简要题意 给定两个次数为 \(d\) 的多项式 \(A, B\) 在 \(0, 1, 2, \dots, d\) 处的点值对 \(10^9+7\) 取模,保证 \(B(x) \equiv A(x+s) ...