主页 > 游戏开发  > 

从零开始用react+tailwindcss+express+mongodb实现一个聊天程序(十)收发消息

从零开始用react+tailwindcss+express+mongodb实现一个聊天程序(十)收发消息
1.聊天框

首先我们完善前端的消息输入框

components下面新建MessageInput组件

import { useState,useRef } from "react" import {X,Image,Send} from "lucide-react" import { useChatStore } from "../store/useChatStore" import toast from "react-hot-toast" const MessageInput = () => { const [text, setText] = useState("") const [imagePreview, setImagePreview] = useState(null) // 预览的图片 const fileInputRef = useRef(null) // 文件输入框 const {sendMessages} = useChatStore(); // 发送消息 const handleImageChange =(e) => { const file = e.target.files[0] if(!file.type.startsWith("image/")) { toast.error("请选择图片文件") return } const reader = new FileReader() reader.onload = () => { setImagePreview(reader.result) } reader.readAsDataURL(file) } const removeImage = () => { setImagePreview(null) if(fileInputRef.current) fileInputRef.current.value = "" } const handleSendMessage = async(e) => { e.preventDefault() if(!text.trim() && !imagePreview) return try { await sendMessages({text:text.trim(),image:imagePreview}) toast.success("发送消息成功") setText("") setImagePreview(null) if(fileInputRef.current) fileInputRef.current.value = "" } catch (error) { console.log(error) toast.error("发送消息失败:",error.message) } } return ( <div className="p-4 w-full"> {imagePreview && ( <div className="mb-3 flex items-center gap-2"> <div className="relative"> <img src={imagePreview} alt="Preview" className="size-20 object-cover rounded-lg border border-zinc-700" /> <button onClick={removeImage} className="absolute -top-1.5 -right-1.5 size-5 rounded-full bg-base-300 flex items-center justify-center" type="button" > <X className="size-3"/> </button> </div> </div> )} {/* 消息输入 */} <form onSubmit={handleSendMessage} className="flex items-center gap-2"> <div className="flex-1 flex gap-2"> <input type="text" className="w-full input input-bordered rounded-lg input-sm sm:input-md" placeholder="输入消息" value={text} onChange={(e) => setText(e.target.value)} /> <input type="file" accept="image/*" className="hidden" ref={fileInputRef} onChange={handleImageChange} /> <button type="button" className={`hidden sm:flex btn btn-circle ${imagePreview?"text-emerald-500":"text-zinc-400"}`} onClick={() => fileInputRef.current.click()} > <Image size={20} /> </button> </div> <button type="submit" className="btn btn-sm btn-circle" disabled={!imagePreview && !text.trim()} > <Send size={22}/> </button> </form> </div> ) } export default MessageInput

聊天的气泡我们参考daisyUi的 chat-start chat-end 效果如下

ChatBox.jsx页面代码

import {useEffect} from "react" import { useChatStore } from "../store/useChatStore" import { useAuthStore } from "../store/useAuthStore" import {formatMessageTime} from "@/lib/util" import ChatHeader from "./ChatHeader" import MessageInput from "./MessageInput" const ChatBox = () => { const {messages, getMessages, isMessagesLoading, selectedUser} = useChatStore() const {authUser} = useAuthStore() useEffect(()=>{ getMessages(selectedUser._id) },[selectedUser._id, getMessages]) if(isMessagesLoading) return <div>Loading...</div> return ( <div className="flex-1 flex flex-col overflow-auto"> {/* 聊天框头部 */} <ChatHeader/> {/* 聊天消息 */} <div className="flex-1 overflow-auto p-4 space-y-4"> {messages.map((message)=> ( <div key={message._id} // 消息的发送者id和当前用户id一致,则显示在右侧,否则显示在左侧 className={`chat ${message.senderId===authUser._id ? 'chat-end' : 'chat-start'}`} > <div className="chat-image avatar"> <div className="size-10 rounded-full border"> <img src={message.senderId === authUser._id ? authUser.profilePic || 'http://via.placeholder /150' : selectedUser.profilePic} alt="" /> </div> </div> <div className="chat-header mb-1"> <time className="text-xs opacity-50 ml-1">{formatMessageTime(message.createdAt)}</time> </div> {/* flex-col 图片和文字上下排列 */} <div className="chat-bubble flex flex-col"> {message.image && ( <img src={message.image} alt="" className="sm:max-w-[200px] rounded-md mb-2" /> )} {message.text && <p>{message.text}</p>} </div> </div> ))} </div> {/* 消息输入 */} <MessageInput/> </div> ) } export default ChatBox

 这是我们在左侧发送消息  右侧用户就能收到消息了 并且自己发送的消息在右侧 收到的消息在左侧  正是用了 chat-start chat-end 这2个class

我们的判断逻辑是

// 消息的发送者id和当前用户id一致,则显示在右侧,否则显示在左侧

className={`chat ${message.senderId===authUser._id ? 'chat-end' : 'chat-start'}`}

思考一个问题 目前我们发送消息给对方 只有刷新页面才能收到新的消息 这是不符合要求的 所以我们引入socket.io 实现实时 的 收发消息 功能。

下篇继续。。。 

标签:

从零开始用react+tailwindcss+express+mongodb实现一个聊天程序(十)收发消息由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“从零开始用react+tailwindcss+express+mongodb实现一个聊天程序(十)收发消息