[译] 使用 Go 和 ReactJS 构建聊天系统 (三)

https://juejin.im/post/5d43d4a3518825640516c6de

本节完整代码:GitHub

本文是关于使用 ReactJS 和 Go 构建聊天应用程序的系列文章的第 3 部分。你可以在这里找到第 2 部分 - 后端实现

Header 组件

我们先来创建一个非常简单的 Header 组件。我们需要在 frontend/src/ 目录下 创建一个叫 components/ 的新目录,并在其中添加一个 Header/ 目录,它将容纳 Header 组件的所有文件。

  1. - src/
  2. - - components/
  3. - - - Header/
  4. - - - - Header.jsx
  5. - - - - index.js
  6. - - - - Header.scss

注意 - 每当我们创建一个新组件时,我们将在 components/ 目录中创建一个新目录,我们会在该目录中创建这三个文件(.jsx,.js,*.scss)。

Header.jsx

我们需要在 Header.jsx 文件中实现函数组件。这将用于呈现网站的标题:

  1. import React from "react";
  2. import "./Header.scss";
  3. const Header = () => (
  4. <div className="header">
  5. <h2>Realtime Chat App</h2>
  6. );
  7. export default Header;

Header.scss

接下来,我们需要加上一些样式。 由于 ReactJS 项目没有处理 scss 文件的能力,因此我们首先需要在 frontend/ 目录中运行以下命令来安装 node-sass

  1. $ yarn add node-sass

安装完成后,我们就可以添加样式了:

  1. .header {
  2. background-color: #15223b;
  3. width: 100%;
  4. margin: 0;
  5. padding: 10px;
  6. color: white;
  7. h2 {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. }

index.js

最后,我们要导出 Header 组件以至于其他组件可以导入它并在它们自己的 render() 函数中展示它:

  1. import Header from "./header.jsx";
  2. export default Header;

更新 App.js

现在已经创建好了 Header 组件,我们需要将它导入 App.js,然后通过将它添加到我们的 render() 函数中来展示它,如下所示:

  1. // App.js
  2. // 从相对路径导入组件
  3. import Header from './components/Header/Header';
  4. // ...
  5. render() {
  6. return (
  7. <div className="App">
  8. <Header />
  9. <button onClick={this.send}>Hit</button>
  10. );
  11. }

保存这个文件后,我们的前端应用程序需要重新编译,然后可以看到 Header 组件成功展示在浏览器页面的顶部。

恭喜 - 你已经成功创建了第一个 React 组件!

历史聊天记录组件

我们已经构建并渲染了一个非常简单的组件,所以我们再来构建一个更复杂一点的组件。

在这个小节中,我们将创建一个历史聊天记录组件,它用来显示我们从 WebSocket 服务收到的所有消息。

我们将在 components/ 目录中创建一个新文件夹叫 ChatHistory/。同样,我们需要为这个组件创建三个文件。

ChatHistory.jsx

我们从 ChatHistory.jsx 文件开始吧。它比之前的要稍微复杂一些,因为我们将构建一个 Class 组件,而不是我们上面 Header 组件的 Function 组件。

注意 - 我们可以使用 ES6 calss 定义类组件。如果你想了解更多有关信息,建议查看官方文档:功能和类组件

在这个组件中,你会注意到有一个 render() 函数。 render() 函数返回一个用于展示此特定组件的 jsx

该组件将通过 props 从 App.js 函数中接收一组聊天消息,然后将它们按列表由上往下展示。

  1. import React, { Component } from "react";
  2. import "./ChatHistory.scss";
  3. class ChatHistory extends Component {
  4. render() {
  5. const messages = this.props.chatHistory.map((msg, index) => (
  6. <p key={index}>{msg.data}</p>
  7. ));
  8. return (
  9. <div className="ChatHistory">
  10. <h2>Chat History</h2>
  11. {messages}
  12. );
  13. }
  14. }
  15. export default ChatHistory;

ChatHistory.scss

我们在 ChatHistory.scss 中来为 ChatHistory 组件添加一个小样式,只是简单的修改一下背景颜色和填充及边距:

  1. .ChatHistory {
  2. background-color: #f7f7f7;
  3. margin: 0;
  4. padding: 20px;
  5. h2 {
  6. margin: 0;
  7. padding: 0;
  8. }
  9. }

Index.js

最后,我们需要导出新组件,就像使用 Header 组件一样,这样它就可以在 App.js 中被导入并展示:

  1. import ChatHistory from "./ChatHistory.jsx";
  2. export default ChatHistory;

更新 App.js 和 api/index.js

现在我们又添加了 ChatHistory 组件,我们需要实际提供一些消息。

在本系列的前一部分中,我们建立了双向通信,回显发送给它的任何内容,因此每当我们点击应用程序中的发送消息按钮时,都会收到一个新消息。

来更新一下 api/index.js 文件和 connect() 函数,以便它从 WebSocket 连接收到新消息时用于回调:

  1. let connect = cb => {
  2. console.log("connecting");
  3. socket.onopen = () => {
  4. console.log("Successfully Connected");
  5. };
  6. socket.onmessage = msg => {
  7. console.log(msg);
  8. cb(msg);
  9. };
  10. socket.onclose = event => {
  11. console.log("Socket Closed Connection: ", event);
  12. };
  13. socket.onerror = error => {
  14. console.log("Socket Error: ", error);
  15. };
  16. };

因此,我们在函数中添加了一个 cb 参数。每当我们收到消息时,都会在第 10 行调用此 cb 会调函数。

当我们完成这些修改,就可以通过 App.js 来添加此回调函数,并在获取新消息时使用 setState 来更新状态。

我们将把 constructor 函数 connect() 移动到 componentDidMount() 函数中调用,该函数将作为组件生命周期的一部分自动调用(译者注:在 render() 方法之后调用)。

  1. // App.js
  2. componentDidMount() {
  3. connect((msg) => {
  4. console.log("New Message")
  5. this.setState(prevState => ({
  6. chatHistory: [...this.state.chatHistory, msg]
  7. }))
  8. console.log(this.state);
  9. });
  10. }

然后更新 App.jsrender() 函数并展示 ChatHistory 组件:

  1. render() {
  2. return (
  3. <div className="App">
  4. <Header />
  5. <ChatHistory chatHistory={this.state.chatHistory} />
  6. <button onClick={this.send}>Hit</button>
  7. );
  8. }

当我们编译并运行前端和后端项目时,可以看到每当点击前端的发送消息按钮时,它会继续通过 WebSocket 连接向后端发送消息,然后后端将其回传给前端,最终在 ChatHistory 组件中成功展示!






总结

我们成功地改进了前端应用程序,并将其视为聊天应用程序。在本系列的下一部分中,将重点关注以下内容:

  • 改进前端:添加新的发送消息组件以允许我们发送自定义消息
  • 改进后端:处理多个客户端以及跨客户端的通信。

下一节:Part 4 - 处理多客户端


原文:tutorialedge.net/projects/ch…

作者:Elliot Forbes 译者:咔叽咔叽 校对:polaris1119

本文由 GCTT 原创编译,Go 中文网 荣誉推出

ft_authoradmin  ft_create_time2019-08-03 16:22
 ft_update_time2019-08-03 16:23