使用 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;
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~