Ant Design Mobile开发移动应用:聊天应用-灵析社区

JOHO

博文正文

一、项目目标

聊天应用:从使用 Ant Design Mobile 的消息列表和输入框组件创建一个简单的聊天应用,用户可以发送和接收消息开始。分步骤扩展完善实现基本功能完整,界面美观的聊天应用项目。

二、项目雏形实现示例代码

当使用 Ant Design Mobile 创建一个简单的聊天应用时,你可以使用其提供的消息列表(List)和输入框组件(InputItem)来实现。以下是一个示例代码,展示了如何使用 Ant Design Mobile 创建一个简单的聊天应用:

import React, { useState } from 'react';
import { List, InputItem, Button } from 'antd-mobile';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      const newMessage = {
        text: inputValue,
        sender: 'user', // or 'bot' for received messages
      };

      setMessages([...messages, newMessage]);
      setInputValue('');
    }
  };

  return (
    <div>
      <List renderHeader={() => 'Chat'}>
        {messages.map((message, index) => (
          <List.Item key={index} className={message.sender}>
            {message.text}
          </List.Item>
        ))}
      </List>
      <div style={{ position: 'fixed', bottom: 0, width: '100%' }}>
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们使用了 useState 钩子来管理消息列表和输入框的状态。messages 数组用于存储聊天中的消息,inputValue 用于存储输入框的值。

handleSendMessage 函数用于处理发送消息的逻辑。它首先检查输入框的值是否为空,然后创建一个新的消息对象,并将其添加到 messages 数组中。最后,清空输入框的值。

在返回的 JSX 中,我们使用 List 组件来显示消息列表。每个消息都被渲染为一个 List.Item 组件。我们使用 map 函数遍历 messages 数组,并为每个消息创建一个 List.Item

输入框部分使用 InputItem 组件,其中 value 属性绑定到 inputValue 状态,onChange 属性用于更新 inputValue 状态。extra 属性用于添加发送按钮,并在按钮点击时调用 handleSendMessage 函数。

这只是一个简单的示例,你可以根据需要进行修改和扩展。希望这可以帮助你开始创建一个使用 Ant Design Mobile 的聊天应用!

三、扩展完善功能美化界面的思路

当扩展聊天应用时,你可以考虑以下几个方面:

  1. 添加消息接收功能:除了用户发送消息外,你可以模拟接收消息的功能。可以使用 setTimeout 或其他方式模拟延迟,并将接收到的消息添加到消息列表中。
  2. 样式和布局:可以使用 Ant Design Mobile 提供的样式和组件来美化你的聊天应用。你可以自定义消息的样式,添加头像、时间戳等元素。
  3. 消息分组和时间戳:如果你希望将消息按照时间分组显示,并显示时间戳,可以对消息进行分组和排序,并在列表中显示时间戳。
  4. 消息发送状态:可以为发送的消息添加发送状态,例如发送中、发送成功或发送失败的状态。可以在发送消息时更新状态,并在列表中显示相应的图标或文本。
  5. 图片和文件发送:除了文本消息,你可以扩展应用程序以支持发送图片、文件等其他类型的消息。可以使用 Ant Design Mobile 的上传组件或其他相关组件来实现。
  6. 消息搜索和筛选:如果你希望用户能够搜索消息或按条件筛选消息,可以添加搜索框和筛选选项,并根据用户输入或选择的条件来过滤消息列表。
  7. 消息持久化和存储:如果你希望在刷新页面或重新打开应用时保留消息记录,可以考虑使用本地存储或后端数据库来持久化存储消息数据。

这些是扩展聊天应用的一些想法,你可以根据自己的需求和创意进行定制和扩展。希望这些建议对你有帮助!

四、实现添加消息接收功能的示例代码

当模拟接收消息的功能时,你可以使用 setTimeout 函数来模拟延迟,并将接收到的消息添加到消息列表中。以下是一个示例代码,展示了如何扩展聊天应用以模拟接收消息:

import React, { useState, useEffect } from 'react';
import { List, InputItem, Button } from 'antd-mobile';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      const newMessage = {
        text: inputValue,
        sender: 'user',
      };

      setMessages([...messages, newMessage]);
      setInputValue('');
    }
  };

  useEffect(() => {
    // 模拟接收消息
    const receiveMessage = () => {
      const newMessage = {
        text: 'Hello from the bot!',
        sender: 'bot',
      };

      setMessages([...messages, newMessage]);
    };

    // 模拟延迟,延迟时间可以根据需要进行调整
    const delay = 3000;
    const timer = setTimeout(receiveMessage, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [messages]);

  return (
    <div>
      <List renderHeader={() => 'Chat'}>
        {messages.map((message, index) => (
          <List.Item key={index} className={message.sender}>
            {message.text}
          </List.Item>
        ))}
      </List>
      <div style={{ position: 'fixed', bottom: 0, width: '100%' }}>
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们使用了 useEffect 钩子来模拟接收消息的功能。在 useEffect 中,我们定义了一个 receiveMessage 函数,用于创建一个新的消息对象,并将其添加到 messages 数组中。然后,我们使用 setTimeout 函数来模拟延迟,延迟时间为 3000 毫秒(3 秒)。在延迟结束后,receiveMessage 函数将被调用。

注意,在 useEffect 的依赖数组中,我们传入了 messages,这是为了确保每次 messages 更新时都会重新设置定时器。

这样,每次发送消息后,经过一段延迟时间,应用程序将模拟接收到一条来自机器人的消息,并将其添加到消息列表中。

希望这个示例代码能够帮助你实现消息接收功能!

五、实现样式和布局的示例代码

当使用 Ant Design Mobile 来美化聊天应用时,你可以使用其提供的样式和组件来自定义消息的样式,并添加头像和时间戳等元素。以下是一个示例代码,展示了如何使用 Ant Design Mobile 来实现样式和布局:

import React, { useState, useEffect } from 'react';
import { List, InputItem, Button, Avatar } from 'antd-mobile';
import './ChatApp.css';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      const newMessage = {
        text: inputValue,
        sender: 'user',
        timestamp: new Date().toLocaleTimeString(),
      };

      setMessages([...messages, newMessage]);
      setInputValue('');
    }
  };

  useEffect(() => {
    // 模拟接收消息
    const receiveMessage = () => {
      const newMessage = {
        text: 'Hello from the bot!',
        sender: 'bot',
        timestamp: new Date().toLocaleTimeString(),
      };

      setMessages([...messages, newMessage]);
    };

    // 模拟延迟,延迟时间可以根据需要进行调整
    const delay = 3000;
    const timer = setTimeout(receiveMessage, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [messages]);

  return (
    <div>
      <List className="message-list">
        {messages.map((message, index) => (
          <List.Item key={index} className={`message-item ${message.sender}`}>
            {message.sender === 'bot' && (
              <Avatar
                className="avatar"
                src="https://example.com/bot-avatar.png"
                alt="Bot Avatar"
              />
            )}
            <div className="message-content">
              <div className="message-text">{message.text}</div>
              <div className="message-timestamp">{message.timestamp}</div>
            </div>
          </List.Item>
        ))}
      </List>
      <div className="input-container">
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们使用了 Ant Design Mobile 的 ListInputItemButtonAvatar 组件来实现样式和布局。

我们使用一个 message-list 的类名来给 List 组件添加样式,并使用 message-item 类名来给每个消息项添加样式。根据消息的发送者,我们添加了 userbot 类名,以便在样式中区分不同的消息。

在每个消息项中,我们使用 Avatar 组件来显示发送者的头像。你可以将头像的 URL 替换为你自己的头像图像 URL。我们还使用 message-content 类名来包装消息的文本内容和时间戳,并使用 message-textmessage-timestamp 类名来给它们添加样式。

最后,我们使用 input-container 类名来给输入框的容器添加样式。

你可以根据自己的需要和设计要求,自定义样式并添加其他元素来美化你的聊天应用。

记得在代码中引入对应的 CSS 文件(例如 ChatApp.css)来定义样式。

希望这个示例代码能够帮助你实现样式和布局!

六、实现消息分组和时间戳的功能的示例代码

如果你希望将消息按照时间分组显示,并显示时间戳,可以对消息进行分组和排序,并在列表中显示时间戳。以下是一个示例代码,展示了如何对消息进行分组和排序,并在列表中显示时间戳:

import React, { useState, useEffect } from 'react';
import { List, InputItem, Button, Avatar } from 'antd-mobile';
import './ChatApp.css';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      const newMessage = {
        text: inputValue,
        sender: 'user',
        timestamp: new Date(),
      };

      setMessages([...messages, newMessage]);
      setInputValue('');
    }
  };

  useEffect(() => {
    // 模拟接收消息
    const receiveMessage = () => {
      const newMessage = {
        text: 'Hello from the bot!',
        sender: 'bot',
        timestamp: new Date(),
      };

      setMessages([...messages, newMessage]);
    };

    // 模拟延迟,延迟时间可以根据需要进行调整
    const delay = 3000;
    const timer = setTimeout(receiveMessage, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [messages]);

  // 按照时间分组和排序消息
  const groupedMessages = messages.reduce((groups, message) => {
    const date = message.timestamp.toDateString();
    if (!groups[date]) {
      groups[date] = [];
    }
    groups[date].push(message);
    return groups;
  }, {});

  const sortedDates = Object.keys(groupedMessages).sort((a, b) => new Date(b) - new Date(a));

  return (
    <div>
      {sortedDates.map((date) => (
        <div key={date}>
          <div className="date-divider">{date}</div>
          <List className="message-list">
            {groupedMessages[date].map((message, index) => (
              <List.Item key={index} className={`message-item ${message.sender}`}>
                {message.sender === 'bot' && (
                  <Avatar
                    className="avatar"
                    src="https://example.com/bot-avatar.png"
                    alt="Bot Avatar"
                  />
                )}
                <div className="message-content">
                  <div className="message-text">{message.text}</div>
                  <div className="message-timestamp">
                    {message.timestamp.toLocaleTimeString()}
                  </div>
                </div>
              </List.Item>
            ))}
          </List>
        </div>
      ))}
      <div className="input-container">
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们使用了 reduce 方法来对消息进行分组和排序。首先,我们将消息按照日期分组,创建一个以日期为键的对象。然后,我们使用 Object.keys 方法获取日期键的数组,并使用 sort 方法将日期数组按照降序排序。

在渲染阶段,我们遍历排序后的日期数组,并为每个日期创建一个分组。在每个分组中,我们使用 date-divider 类名来显示日期分隔线。

在每个日期分组中,我们使用 message-list 类名给 List 组件添加样式,并遍历该日期下的消息数组。对于每条消息,我们按照之前的方式进行渲染,并在时间戳上使用 toLocaleTimeString 方法来显示格式化的时间。

最后,我们在输入框的容器中添加了 input-container 类名来给其添加样式。

记得在代码中引入对应的 CSS 文件(例如 ChatApp.css)来定义样式。

希望这个示例代码能够帮助你实现消息分组和时间戳的功能!

七、实现消息发送状态功能的示例代码

如果你想为发送的消息添加发送状态(例如发送中、发送成功或发送失败的状态),可以在发送消息时更新状态,并在列表中显示相应的图标或文本。以下是一个示例代码,展示了如何实现消息发送状态的功能:

import React, { useState, useEffect } from 'react';
import { List, InputItem, Button, Avatar } from 'antd-mobile';
import './ChatApp.css';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      const newMessage = {
        id: new Date().getTime(), // 添加消息的唯一标识符
        text: inputValue,
        sender: 'user',
        timestamp: new Date(),
        status: 'sending', // 初始状态为发送中
      };

      setMessages([...messages, newMessage]);
      setInputValue('');

      // 模拟发送消息的延迟
      setTimeout(() => {
        // 更新消息状态为发送成功
        setMessages((prevMessages) =>
          prevMessages.map((message) =>
            message.id === newMessage.id ? { ...message, status: 'sent' } : message
          )
        );

        // 模拟接收消息
        setTimeout(() => {
          const receivedMessage = {
            id: new Date().getTime(),
            text: 'Hello from the bot!',
            sender: 'bot',
            timestamp: new Date(),
            status: 'received',
          };

          setMessages((prevMessages) => [...prevMessages, receivedMessage]);
        }, 2000);
      }, 2000);
    }
  };

  return (
    <div>
      <List className="message-list">
        {messages.map((message) => (
          <List.Item
            key={message.id}
            className={`message-item ${message.sender} ${message.status}`}
          >
            {message.sender === 'bot' && (
              <Avatar
                className="avatar"
                src="https://example.com/bot-avatar.png"
                alt="Bot Avatar"
              />
            )}
            <div className="message-content">
              <div className="message-text">{message.text}</div>
              <div className="message-timestamp">
                {message.timestamp.toLocaleTimeString()}
              </div>
              {message.status === 'sending' && <div className="message-status">Sending...</div>}
              {message.status === 'sent' && (
                <div className="message-status">
                  <i className="icon-success" /> Sent
                </div>
              )}
              {message.status === 'received' && (
                <div className="message-status">
                  <i className="icon-success" /> Received
                </div>
              )}
            </div>
          </List.Item>
        ))}
      </List>
      <div className="input-container">
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们为每条消息添加了一个唯一的 id 属性,用于标识消息。并且我们为每条消息添加了一个 status 属性,用于表示消息的发送状态。

在发送消息时,我们首先将消息的状态设置为 “sending”,表示发送中。然后使用 setTimeout 模拟发送消息的延迟。在延迟结束后,我们更新消息的状态为 “sent”,表示发送成功。然后再使用 setTimeout 模拟接收消息的延迟,并添加接收到的消息到消息列表中,并将其状态设置为 “received”,表示接收成功。

在消息列表的渲染中,我们根据消息的状态添加相应的类名,例如 “sending”、“sent” 或 “received”。这样可以根据状态来显示不同的图标或文本。

在消息内容的底部,我们使用 message-status 类名来给发送状态添加样式,并根据消息的状态显示相应的文本,例如 “Sending…”、“Sent” 或 “Received”。

你可以根据自己的需要和设计要求,自定义样式和图标来表示不同的发送状态。

希望这个示例代码能够帮助你实现消息发送状态的功能!

八、实现发送图片和文件功能的示例代码

如果你想扩展应用程序以支持发送图片和文件等其他类型的消息,可以使用 Ant Design Mobile 的上传组件或其他相关组件来实现。以下是一个示例代码,展示了如何实现发送图片和文件的功能:

import React, { useState, useEffect } from 'react';
import { List, InputItem, Button, Avatar, Toast } from 'antd-mobile';
import { UploadOutlined } from '@ant-design/icons';
import './ChatApp.css';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');
  const [file, setFile] = useState(null);

  const handleSendMessage = () => {
    if (inputValue.trim() !== '' || file) {
      const newMessage = {
        id: new Date().getTime(),
        text: inputValue,
        sender: 'user',
        timestamp: new Date(),
        file: file,
      };

      setMessages([...messages, newMessage]);
      setInputValue('');
      setFile(null);
    }
  };

  const handleFileChange = (e) => {
    const selectedFile = e.target.files[0];
    setFile(selectedFile);
  };

  useEffect(() => {
    // 模拟接收消息
    const receiveMessage = () => {
      const newMessage = {
        id: new Date().getTime(),
        text: 'Hello from the bot!',
        sender: 'bot',
        timestamp: new Date(),
      };

      setMessages([...messages, newMessage]);
    };

    // 模拟延迟,延迟时间可以根据需要进行调整
    const delay = 3000;
    const timer = setTimeout(receiveMessage, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [messages]);

  return (
    <div>
      <List className="message-list">
        {messages.map((message) => (
          <List.Item
            key={message.id}
            className={`message-item ${message.sender}`}
          >
            {message.sender === 'bot' && (
              <Avatar
                className="avatar"
                src="https://example.com/bot-avatar.png"
                alt="Bot Avatar"
              />
            )}
            <div className="message-content">
              {message.text && <div className="message-text">{message.text}</div>}
              {message.file && (
                <div className="message-file">
                  <a href={URL.createObjectURL(message.file)} download={message.file.name}>
                    {message.file.name}
                  </a>
                </div>
              )}
              <div className="message-timestamp">
                {message.timestamp.toLocaleTimeString()}
              </div>
            </div>
          </List.Item>
        ))}
      </List>
      <div className="input-container">
        <input type="file" onChange={handleFileChange} style={{ display: 'none' }} ref={(input) => this.fileInput = input} />
        <Button
          icon={<UploadOutlined />}
          onClick={() => this.fileInput.click()}
        >
          Upload File
        </Button>
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们添加了一个 file 状态来存储用户选择的文件。当用户选择文件时,我们将文件存储在 file 状态中。

我们使用 <input type="file" /> 元素来实现文件选择功能,并将其设置为不可见。然后,我们使用 Ant Design Mobile 的按钮组件,并添加一个上传图标。当用户点击上传按钮时,我们触发 <input type="file" /> 元素的点击事件,以便用户选择文件。

在发送消息时,我们检查输入框的值和文件状态。如果输入框的值或文件状态不为空,则创建一个新的消息对象,并将其添加到消息列表中。我们还将文件对象存储在消息对象的 file 属性中。

在消息列表的渲染中,我们根据消息对象的 textfile 属性来渲染文本消息和文件消息。对于文件消息,我们创建一个下载链接,使用户能够下载文件。

希望这个示例代码能够帮助你实现发送图片和文件的功能!请注意,你可能需要根据自己的需求和文件类型进行适当的调整和处理。

九、实现消息搜索和筛选功能的示例代码

如果你希望用户能够搜索消息或按条件筛选消息,可以添加搜索框和筛选选项,并根据用户输入或选择的条件来过滤消息列表。以下是一个示例代码,展示了如何实现消息搜索和筛选的功能:

import React, { useState, useEffect } from 'react';
import { List, InputItem, Button, Avatar, Toast } from 'antd-mobile';
import { SearchOutlined } from '@ant-design/icons';
import './ChatApp.css';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');
  const [searchTerm, setSearchTerm] = useState('');
  const [filteredMessages, setFilteredMessages] = useState([]);

  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      const newMessage = {
        id: new Date().getTime(),
        text: inputValue,
        sender: 'user',
        timestamp: new Date(),
      };

      setMessages([...messages, newMessage]);
      setInputValue('');
    }
  };

  const handleSearch = () => {
    const filtered = messages.filter((message) =>
      message.text.toLowerCase().includes(searchTerm.toLowerCase())
    );

    setFilteredMessages(filtered);
  };

  useEffect(() => {
    setFilteredMessages(messages);
  }, [messages]);

  return (
    <div>
      <div className="search-container">
        <InputItem
          placeholder="Search messages"
          value={searchTerm}
          onChange={(value) => setSearchTerm(value)}
          extra={
            <Button type="primary" onClick={handleSearch} icon={<SearchOutlined />} />
          }
        />
      </div>
      <List className="message-list">
        {filteredMessages.map((message) => (
          <List.Item
            key={message.id}
            className={`message-item ${message.sender}`}
          >
            {message.sender === 'bot' && (
              <Avatar
                className="avatar"
                src="https://example.com/bot-avatar.png"
                alt="Bot Avatar"
              />
            )}
            <div className="message-content">
              <div className="message-text">{message.text}</div>
              <div className="message-timestamp">
                {message.timestamp.toLocaleTimeString()}
              </div>
            </div>
          </List.Item>
        ))}
      </List>
      <div className="input-container">
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们添加了一个 searchTerm 状态来存储用户输入的搜索关键词。当用户输入搜索关键词时,我们更新 searchTerm 状态。

在搜索时,我们使用 filter 方法来过滤消息列表,只保留包含搜索关键词的消息。我们将过滤后的消息存储在 filteredMessages 状态中,并在消息列表的渲染中使用它来显示筛选后的消息。

在搜索框的渲染中,我们使用 Ant Design Mobile 的输入框组件和搜索图标。当用户点击搜索按钮时,我们调用 handleSearch 函数来执行搜索操作。

在消息列表的渲染中,我们根据 filteredMessages 状态来渲染筛选后的消息。

请注意,这只是一个简单的示例代码,仅演示了如何实现消息搜索和筛选的基本功能。你可以根据自己的需求和设计要求进行修改和扩展。

希望这个示例代码能够帮助你实现消息搜索和筛选的功能!

十、实现消息持久化存储功能的示例代码

如果你希望在刷新页面或重新打开应用时保留消息记录,可以考虑使用本地存储或后端数据库来持久化存储消息数据。以下是一个示例代码,展示了如何使用浏览器的本地存储(localStorage)来实现消息的持久化存储:

import React, { useState, useEffect } from 'react';
import { List, InputItem, Button, Avatar, Toast } from 'antd-mobile';
import { SearchOutlined } from '@ant-design/icons';
import './ChatApp.css';

const ChatApp = () => {
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');
  const [searchTerm, setSearchTerm] = useState('');
  const [filteredMessages, setFilteredMessages] = useState([]);

  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      const newMessage = {
        id: new Date().getTime(),
        text: inputValue,
        sender: 'user',
        timestamp: new Date(),
      };

      const updatedMessages = [...messages, newMessage];
      setMessages(updatedMessages);
      setInputValue('');

      // 保存消息到本地存储
      localStorage.setItem('chatMessages', JSON.stringify(updatedMessages));
    }
  };

  const handleSearch = () => {
    const filtered = messages.filter((message) =>
      message.text.toLowerCase().includes(searchTerm.toLowerCase())
    );

    setFilteredMessages(filtered);
  };

  useEffect(() => {
    // 从本地存储中获取之前保存的消息
    const storedMessages = localStorage.getItem('chatMessages');
    if (storedMessages) {
      setMessages(JSON.parse(storedMessages));
    }
  }, []);

  useEffect(() => {
    setFilteredMessages(messages);
  }, [messages]);

  return (
    <div>
      <div className="search-container">
        <InputItem
          placeholder="Search messages"
          value={searchTerm}
          onChange={(value) => setSearchTerm(value)}
          extra={
            <Button type="primary" onClick={handleSearch} icon={<SearchOutlined />} />
          }
        />
      </div>
      <List className="message-list">
        {filteredMessages.map((message) => (
          <List.Item
            key={message.id}
            className={`message-item ${message.sender}`}
          >
            {message.sender === 'bot' && (
              <Avatar
                className="avatar"
                src="https://example.com/bot-avatar.png"
                alt="Bot Avatar"
              />
            )}
            <div className="message-content">
              <div className="message-text">{message.text}</div>
              <div className="message-timestamp">
                {message.timestamp.toLocaleTimeString()}
              </div>
            </div>
          </List.Item>
        ))}
      </List>
      <div className="input-container">
        <InputItem
          placeholder="Type a message"
          value={inputValue}
          onChange={(value) => setInputValue(value)}
          extra={
            <Button type="primary" onClick={handleSendMessage}>
              Send
            </Button>
          }
        />
      </div>
    </div>
  );
};

export default ChatApp;

在上面的代码中,我们使用 localStorage 对象来保存和获取消息数据。当用户发送新消息时,我们将更新的消息列表保存到本地存储中。在组件的初始加载时,我们从本地存储中获取之前保存的消息,并将其设置为初始的消息列表。

请注意,localStorage 对象的存储容量有限,通常在几个兆字节。如果你的应用程序需要存储大量的消息数据,或者需要多用户之间共享消息数据,你可能需要考虑使用后端数据库来进行持久化存储。

希望这个示例代码能够帮助你实现消息的持久化存储!请根据你的实际需求和开发环境进行相应的调整和改进。

十一、初步整合尝试写完整项目示例代码

当然!下面是一个完整的聊天应用示例代码,包括 HTML、CSS 和 JavaScript 部分:

HTML:

<!DOCTYPE html>
<html>
<head>
  <title>Chat App</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
  <div class="container">
    <div class="search-container">
      <input type="text" id="search-input" placeholder="Search messages...">
    </div>
    <ul class="message-list" id="message-list"></ul>
    <div class="input-container">
      <input type="text" id="message-input" placeholder="Type a message...">
      <button id="send-button">Send</button>
    </div>
  </div>

  <script src="app.js"></script>
</body>
</html>

CSS (styles.css):

.container {
  max-width: 400px;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #ccc;
}

.search-container {
  margin-bottom: 10px;
}

.message-list {
  max-height: 300px;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid #ccc;
}

.message-item {
  margin-bottom: 10px;
}

.user .message-text {
  background-color: #e2f0ff;
  color: #000;
}

.bot .message-text {
  background-color: #f0f0f0;
  color: #000;
}

.message-text {
  padding: 8px;
  border-radius: 8px;
}

.message-timestamp {
  font-size: 12px;
  color: #888;
}

.input-container {
  margin-top: 10px;
}

#message-input {
  width: 70%;
  padding: 5px;
}

#send-button {
  padding: 5px 10px;
}

JavaScript (app.js):

// Get DOM elements
const searchInput = document.getElementById('search-input');
const messageList = document.getElementById('message-list');
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');

// Function to create a new message item
function createMessageItem(sender, content, timestamp) {
  const messageItem = document.createElement('li');
  messageItem.classList.add('message-item');
  messageItem.classList.add(sender);

  const avatar = document.createElement('div');
  avatar.classList.add('avatar');
  // Add avatar image or initials for the sender

  const messageContent = document.createElement('div');
  messageContent.classList.add('message-content');

  const messageText = document.createElement('div');
  messageText.classList.add('message-text');
  messageText.textContent = content;

  const messageTimestamp = document.createElement('div');
  messageTimestamp.classList.add('message-timestamp');
  messageTimestamp.textContent = timestamp;

  messageContent.appendChild(messageText);
  messageContent.appendChild(messageTimestamp);

  messageItem.appendChild(avatar);
  messageItem.appendChild(messageContent);

  return messageItem;
}

// Function to add a new message to the message list
function addMessage(sender, content, timestamp) {
  const messageItem = createMessageItem(sender, content, timestamp);
  messageList.appendChild(messageItem);
  messageList.scrollTop = messageList.scrollHeight; // Scroll to the bottom of the list
}

// Event listener for send button click
sendButton.addEventListener('click', function() {
  const message = messageInput.value.trim();
  if (message !== '') {
    const timestamp = new Date().toLocaleTimeString();
    addMessage('user', message, timestamp);
    messageInput.value = '';
  }
});

// Event listener for Enter key press in message input
messageInput.addEventListener('keyup', function(event) {
  if (event.key === 'Enter') {
    sendButton.click();
  }
});

// Example initial messages
addMessage('bot', 'Hello! How can I assist you?', '10:00 AM');
addMessage('user', 'I have a question about your products.', '10:01 AM');
addMessage('bot', 'Sure, what would you like to know?', '10:02 AM');

这个示例代码包括了一个简单的聊天应用的 HTML 结构、CSS 样式和 JavaScript 逻辑。你可以将这些代码保存到对应的文件中(HTML 文件保存为 index.html,CSS 文件保存为 styles.css,JavaScript 文件保存为 app.js),然后在浏览器中打开 index.html 文件以查看聊天应用的效果。

这个示例代码提供了一个基本的聊天应用框架,你可以根据自己的需求和设计要求进行修改和扩展。例如,你可以添加消息搜索功能、消息发送状态、用户头像等。

十二、添加功能微调优化完整项目示例代码

当然!下面是一个进一步改进的聊天应用示例代码,包括 HTML、CSS 和 JavaScript 部分:

HTML:

<!DOCTYPE html>
<html>
<head>
  <title>Chat App</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
  <div class="container">
    <div class="search-container">
      <input type="text" id="search-input" placeholder="Search messages...">
    </div>
    <ul class="message-list" id="message-list"></ul>
    <div class="input-container">
      <input type="text" id="message-input" placeholder="Type a message...">
      <button id="send-button">Send</button>
    </div>
  </div>

  <script src="app.js"></script>
</body>
</html>

CSS (styles.css):

.container {
  max-width: 400px;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #ccc;
}

.search-container {
  margin-bottom: 10px;
}

.message-list {
  max-height: 300px;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid #ccc;
}

.message-item {
  display: flex;
  align-items: flex-start;
  margin-bottom: 10px;
}

.user {
  justify-content: flex-end;
}

.bot {
  justify-content: flex-start;
}

.avatar {
  width: 40px;
  height: 40px;
  margin-right: 10px;
  border-radius: 50%;
}

.message-content {
  display: flex;
  flex-direction: column;
}

.message-text {
  padding: 8px;
  border-radius: 8px;
  margin-bottom: 4px;
}

.user .message-text {
  background-color: #e2f0ff;
  color: #000;
}

.bot .message-text {
  background-color: #f0f0f0;
  color: #000;
}

.message-timestamp {
  font-size: 12px;
  color: #888;
}

.input-container {
  margin-top: 10px;
}

#message-input {
  width: 70%;
  padding: 5px;
}

#send-button {
  padding: 5px 10px;
}

JavaScript (app.js):

// Get DOM elements
const searchInput = document.getElementById('search-input');
const messageList = document.getElementById('message-list');
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');

// Function to create a new message item
function createMessageItem(sender, content, timestamp) {
  const messageItem = document.createElement('li');
  messageItem.classList.add('message-item');
  messageItem.classList.add(sender);

  const avatar = document.createElement('div');
  avatar.classList.add('avatar');
  // Add avatar image or initials for the sender

  const messageContent = document.createElement('div');
  messageContent.classList.add('message-content');

  const messageText = document.createElement('div');
  messageText.classList.add('message-text');
  messageText.textContent = content;

  const messageTimestamp = document.createElement('div');
  messageTimestamp.classList.add('message-timestamp');
  messageTimestamp.textContent = timestamp;

  messageContent.appendChild(messageText);
  messageContent.appendChild(messageTimestamp);

  messageItem.appendChild(avatar);
  messageItem.appendChild(messageContent);

  return messageItem;
}

// Function to add a new message to the message list
function addMessage(sender, content, timestamp) {
  const messageItem = createMessageItem(sender, content, timestamp);
  messageList.appendChild(messageItem);
  messageList.scrollTop = messageList.scrollHeight; // Scroll to the bottom of the list
}

// Event listener for send button click
sendButton.addEventListener('click', function() {
  const message = messageInput.value.trim();
  if (message !== '') {
    const timestamp = new Date().toLocaleTimeString();
    addMessage('user', message, timestamp);
    messageInput.value = '';
    simulateBotResponse();
  }
});

// Event listener for Enter key press in message input
messageInput.addEventListener('keyup', function(event) {
  if (event.key === 'Enter') {
    sendButton.click();
  }
});

// Function to simulate a bot response
function simulateBotResponse() {
  const messages = [
    "I'm sorry, I don't have the information you're looking for.",
    "Our customer support team will be happy to assist you.",
    "Can I help you with anything else?",
    "Thank you for contacting us!"
  ];
  const randomIndex = Math.floor(Math.random() * messages.length);
  const botMessage = messages[randomIndex];
  const timestamp = new Date().toLocaleTimeString();
  setTimeout(function() {
    addMessage('bot', botMessage, timestamp);
  }, 1000);
}

// Example initial messages
addMessage('bot', 'Hello! How can I assist you?', '10:00 AM');
addMessage('user', 'I have a question about your products.', '10:01 AM');
addMessage('bot', 'Sure, what would you like to know?', '10:02 AM');

在这个改进的示例代码中,我们添加了以下功能和改进:

  1. 添加了一个搜索输入框,用于搜索消息。
  2. 修改了消息项的样式,使其显示为左对齐或右对齐,以区分用户消息和机器人消息。
  3. 添加了用户和机器人的头像占位符,你可以根据需要替换为实际的头像图片或头像字母。
  4. 添加了消息发送后的模拟机器人回复功能,以模拟聊天对话。

此外,我们还对 CSS 样式进行了一些微调,以改进界面的外观。

希望这个进一步改进的示例代码能够满足你的需求!如果你有任何进一步的问题,请随时提问。


阅读量:518

点赞量:0

收藏量:0