导读:在这篇文章中,我们将对对话页面进行编码。                                       
本文字数:5504,阅读时长大约:6分钟
https://linux.cn/article-12723-1.html

作者:Nicolás Parada
译者:XianLei Gao
本文是该系列的第九篇,也是最后一篇。
◈ 第一篇: 模式
◈ 第二篇: OAuth
◈ 第三篇: 对话
◈ 第四篇: 消息
◈ 第五篇: 实时消息
◈ 第六篇: 仅用于开发的登录
◈ 第七篇: Access 页面
◈ 第八篇: Home 页面
在这篇文章中,我们将对对话(conversation)页面进行编码。此页面是两个用户之间的聊天室。在顶部我们将显示其他参与者的信息,下面接着的是最新消息列表,以及底部的消息表单。
聊天标题
让我们从创建 static/pages/conversation-page.js 文件开始,它包含以下内容:
import
http
from'../http.js'import{
navigate
}from'../router.js'import{
avatar
,
escapeHTML
}from'../shared.js'exportdefaultasyncfunctionconversationPage(conversationID){let
conversation
try{
conversation
=awaitgetConversation(
conversationID
)}catch(
err
){alert(
err
.
message
)navigate('/',true)return}const
template
=
document
.createElement('template')
template
.
innerHTML
=
`

<div>

<a href="/">← Back</a>

${avatar(conversation.otherParticipant)}
<span>
${conversation.otherParticipant.username}
</span>

</div>

<!-- message list here -->

<!-- message form here -->

`
const
page
=
template
.
content
return
page
}functiongetConversation(id){return
http
.get('/api/conversations/'+
id
)}
此页面接收路由从 URL 中提取的会话 ID。
首先,它向 /api/ conversations/{conversationID} 发起一个 GET 请求,以获取有关对话的信息。如果出现错误,我们会将其显示,并重定向回 /。然后我们呈现有关其他参与者的信息。
对话列表
我们也会获取最新的消息并显示它们。
let
conversation
,
messages
try{[
conversation
,
messages
]=await
Promise
.all([getConversation(
conversationID
),getMessages(
conversationID
),])}
更新 conversationPage() 函数以获取消息。我们使用 Promise.all() 同时执行这两个请求。
functiongetMessages(conversationID){return
http
.get(`/api/conversations/${conversationID}/messages`)}
发起对 /api/conversations/{conversationID}/messages 的 GET 请求可以获取对话中的最新消息。
<ol id="messages"></ol>
现在,将该列表添加到标记中。
const
messagesOList
=
page
.getElementById('messages')for(const
message
of
messages
.reverse()){
messagesOList
.appendChild(renderMessage(
message
))}
这样我们就可以将消息附加到列表中了。我们以时间倒序来显示它们。
functionrenderMessage(message){const
messageContent
=escapeHTML(
message
.
content
)const
messageDate
=newDate(
message
.
createdAt
).toLocaleString()const
li
=
document
.createElement('li')if(
message
.
mine
){
li
.
classList
.add('owned')}
li
.
innerHTML
=
`

<p>
${messageContent}
</p>

<time>
${messageDate}
</time>

`
return
li
}
每个消息条目显示消息内容本身及其时间戳。使用 .mine,我们可以将不同的 css 类附加到条目,这样您就可以将消息显示在右侧。
消息表单
<form id="message-form"><input type="text"placeholder="Type something"maxlength="480"required><button>
Send
</button></form>
将该表单添加到当前标记中。
page
.getElementById('message-form').
onsubmit
=messageSubmitter(
conversationID
)
将事件监听器附加到 “submit” 事件。
functionmessageSubmitter(conversationID){returnasyncev=>{
ev
.preventDefault()const
form
=
ev
.
currentTarget
const
input
=
form
.querySelector('input')const
submitButton
=
form
.querySelector('button')
input
.
disabled
=true
submitButton
.
disabled
=truetry{const
message
=awaitcreateMessage(
input
.
value
,
conversationID
)
input
.
value
=''const
messagesOList
=
document
.getElementById('messages')if(
messagesOList
===null){return}
messagesOList
.appendChild(renderMessage(
message
))}catch(
err
){if(
err
.
statusCode
===422){
input
.setCustomValidity(
err
.
body
.
errors
.
content
)}else{alert(
err
.
message
)}}finally{
input
.
disabled
=false
submitButton
.
disabled
=falsesetTimeout(()=>{
input
.focus()},0)}}}functioncreateMessage(content, conversationID){return
http
.post(`/api/conversations/${conversationID}/messages`,{
content
})}
我们利用 partial application 在 “submit” 事件处理程序中获取对话 ID。它 从输入中获取消息内容,并用它对 /api/conversations/{conversationID}/messages 发出 POST 请求。然后将新创建的消息添加到列表中。
消息订阅
为了实现实时,我们还将订阅此页面中的消息流。
page
.addEventListener('disconnect',subscribeToMessages(messageArriver(
conversationID
)))
将该行添加到 conversationPage() 函数中。
functionsubscribeToMessages(cb){return
http
.subscribe('/api/messages',
cb
)}functionmessageArriver(conversationID){returnmessage=>{if(
message
.
conversationID
!==
conversationID
){return}const
messagesOList
=
document
.getElementById('messages')if(
messagesOList
===null){return}
messagesOList
.appendChild(renderMessage(
message
))readMessages(
message
.
conversationID
)}}functionreadMessages(conversationID){return
http
.post(`/api/conversations/${conversationID}/read_messages`)}
在这里我们仍然使用这个应用的部分来获取会话 ID。当新消息到达时,我们首先检查它是否来自此对话。如果是,我们会将消息条目预先添加到列表中,并向 /api/conversations/{conversationID}/read_messages 发起 POST 一个请求,以更新参与者上次阅读消息的时间。

本系列到此结束。消息应用现在可以运行了。
◈ 源代码
◈ 演示

作者:Nicolás Parada 选题:lujun9972 译者:gxlct008 校对:wxy
本文由 LCTT 原创编译,Linux中国 荣誉推出
继续阅读
阅读原文