使用 OnsenUI 和 Horizon 的实时聊天应用程序!
介绍
许多现代应用(例如 Twitter 或 Facebook)都是实时运行的:它们会在有新信息时立即更新,而无需用户手动刷新。借助RethinkDB和 JavaScript 框架Horizon等现代实时数据库,创建实时应用程序就像编写任何其他 JavaScript 应用程序一样简单。
在本教程中,我们将使用MobX和Onsen UI 的 React 组件构建一个简单的聊天应用程序。
该应用程序的完整源代码可在GitHub上找到。我们的最终结果将如下所示:
      <div style="display: flex; margin: 40px 0;" >
  <div style="flex-grow: 1;"> </div>
  <div style="background-image: url('https://onsen.io/blog/content/images/2016/Feb/iphone6.png'); width: 401px; height: 806px; ">
    <iframe scrolling="yes" style="margin-top: 92px; margin-left: 26px;" src="https://onsenhorizon.herokuapp.com" width="349" height="617" scrolling="no" class="lazy-hidden"></iframe>
  </div>
  <div style="flex-grow: 1;"> </div>
</div>
    
我们首先了解一下 RethinkDB 和 Horizon.js。然后我们将构建我们的应用程序。
什么是 RethinkDB 和 Horizon.js?
RethinkDB 是一个实时数据库。RethinkDB 与传统数据库的区别在于能够监听数据库变化。持续监听使实时更新变得非常容易。
Horizon.js 是一个 JavaScript 框架,可以更轻松地与 RethinkDB 交互。您可以通过调用以下 npm 命令来安装 Horizon:
      $ npm install -g horizon
    
使用以下命令,可以在端口 5000 上以开发模式启动一个简单的 Horizon 服务器:
      $ hz serve --dev --bind all -p 5000
    
参数--bind all使其可在整个网络中访问。在开发模式下,没有用户身份验证,也没有安全规则。在本教程中,我们不会处理身份验证,但如果您有兴趣了解它,请查看文档。
要在我们的应用程序中启动 Horizon,我们只需使用connect()函数
      import Horizon from "@horizon/client";
const horizon = Horizon();
horizon.onReady(() => {
  console.log("horizon is ready");
});
console.log("connect horizon");
horizon.connect();
    
对于聊天应用程序,我们将创建两个表,一个用于房间 - 该表仅包含房间名称及其 ID - 另一个表用于房间 ID 、消息本身和用户名。
为了创建房间和消息,我们可以编写一些简单的函数:
      createRoom: roomName => {
  horizon("chatRooms").store({ name: roomName });
};
createMessage: (authorName, roomID, message) => {
  horizon("messages").store({
    author: authorName,
    date: new Date(),
    message: message,
    roomID: roomID
  });
};
    
函数createRoom使用提供的房间名称创建一个简单的房间。createMessage为房间创建一条消息。
有趣的部分是我们如何监听数据库的变化。我们想要按日期排序获取一个房间的所有消息:
      horizon("messages")
  .findAll({ roomID: roomID })
  .order("date")
  .watch()
  .subscribe(data => {
    // update messages here
  });
    
每次更新数据时都会调用subscribe()中的函数。在 React 中,我们几乎不需要任何代码就可以更新状态并更新数据。
现在我们可以创建聊天室并创建消息了,还剩下什么呢?实际上,这几乎就是我们的应用程序所需的所有后端代码!
现在让我们开始使用 MobX 和 React Components 构建 Onsen UI。
在 Onsen UI 中构建组件
Onsen UI 的 React Components 可以非常轻松地构建带有导航的简单页面,而无需太多代码。我们的应用程序将包含两个屏幕:第一个将是一个简单的登录屏幕,用户可以在其中输入聊天室的名称和用户名。我们将在名为App的组件中呈现所有内容,该组件将包含子项:
      import React from "react";
import { render } from "react-dom";
import AppState from "./AppState";
import App from "./App";
import Horizon from "@horizon/client";
const horizon = Horizon({ host: "localhost:5000" });
const appState = new AppState(horizon);
horizon.onReady(() => {
  console.log("horizon is ready");
  render(<App appState={appState} />, document.getElementById("root"));
});
console.log("connect horizon");
horizon.connect();
    
在开始查看视图之前,让我们先看看应用程序状态。应用程序状态通过MobX进行管理。MobX 是一个 JavaScript 库,它使用可观察对象在观察到的变量发生变化时自动执行某些操作。在 React 的情况下,如果状态所依赖的变量发生变化,MobX 会调用setState()。如果你想了解更多关于 MobX 的信息,我强烈建议你看看我们最近的教程,该教程使用 MobX 创建了一个简单的秒表。
以下代码定义了应用程序状态。应用程序状态将包含当前用户名、聊天室、与 Horizon 的数据库连接以及一些其他与页面相关的信息。在 MobX 中,我们用装饰器@observable标记变量,以指示 MobX 应该观察它。如果它们发生变化,关联的视图将自动调用重新渲染。标有@action的函数是更改可观察变量的函数,而@computed函数 getter 依赖于可观察变量,只有在关联变量发生变化后才会更新。
      import { computed, observable, action } from "mobx";
class ChatRoom {
  @observable name;
  id;
  constructor(data) {
    this.name = data.name;
    this.id = data.id;
  }
}
export class ChatRoomPageState {
  @observable text = "";
  @action
  setText(text) {
    this.text = text;
  }
  @action
  resetText() {
    this.text = "";
  }
}
class AppState {
  horizon;
  @observable userName;
  @observable roomName = "onsenui";
  @observable chatRooms = [];
  @observable loading = false;
  @observable messages = [];
  @observable newMessage = false;
  constructor(horizon) {
    this.horizon = horizon;
    this.chatRooms = [];
  }
  @computed
  get messageList() {
    var list = this.messages.map(el => el);
    for (var i = 1; i < list.length; i++) {
      if (list[i - 1].author === list[i].author) {
        list[i].showAuthor = false;
      } else {
        list[i].showAuthor = true;
      }
    }
    if (list.length > 0) {
      list[0].showAuthor = true;
    }
    return list;
  }
  @computed
  get lastAuthor() {
    if (this.messages.length === 0) {
      return "";
    }
    return this.messages[this.messages.length - 1].author;
  }
  @action
  setMessages(data) {
    this.messages = data;
  }
  @action
  hideMessageNotification() {
    this.newMessage = false;
  }
  @action
  showMessageNotification() {
    if (this.newMessage) return;
    this.newMessage = true;
    setTimeout(() => (this.newMessage = false), 2000);
  }
  @action
  setChatRoom(data) {
    this.chatRooms = data.map(el => new ChatRoom(el));
  }
}
export default AppState;
    
登录屏幕
在下面的解释中,我们将介绍应用程序的结构和组件的基本交互。感兴趣的读者可以在GitHub上查找更多详细信息。
对于导航,我们将使用 Onsen UI Navigator。我们为其提供一个初始路由,该路由将包含我们将渲染到的组件。在我们的例子中,此组件将是LoginPage。
      import React, { Component } from "react";
import ons from "onsenui";
import {
  Modal,
  Page,
  Col,
  Row,
  BottomToolbar,
  List,
  ListItem,
  Button,
  Navigator,
  Toolbar,
  Input
} from "react-onsenui";
// ... LoginPage definition omitted for simplicity
// it would render to something like <Page> .. </Page>
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.renderPage = this.renderPage.bind(this);
  }
  renderPage(route, navigator) {
    const props = route.props || {};
    props.navigator = navigator;
    return React.createElement(route.component, route.props);
  }
  render() {
    return (
      <Navigator
        initialRoute={{
          component: LoginPage,
          props: {
            appState: this.props.appState
          }
        }}
        renderPage={this.renderPage}
      />
    );
  }
}
export default App;
    
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
 
 
                                 
                                     
                                     
                                     
                                     
                                     
                                 
                             
                                     
                                     
                                     
                                     
     
    
 
             
   
        
请先 登录后发表评论 ~