在vanilla JS中,我正在向服务器发出get
请求,以在初始页面加载后检索项目列表(对话中的消息列表)。当发送回复(post
请求)时,我想将新消息附加到现有消息列表而不刷新整个页面(想想React)。
这适用于页面最初加载的时间:
window.addEventListener('load', () => {
axios.get(get_url).then((res) => {
// Get conversation
})
})
然后,发送回复:
const sendReply = () => {
const reply = document.getElementById('replyMessage').value
axios.post(post_url, {
// data
})
.then(function(res) {
if (res.status === 201) {
window.location.reload(true)
}
})
}
正如您所看到的,我正在刷新整个页面,这感觉并不理想。应该有更好的方法将新消息附加到现有对话。 可以用vanilla JS完成吗?
更新
如果有人好奇我是如何解决这个问题的,那就是我所做的:
const sendReply = () => {
const replyText = document.getElementById('replyMessage').value // Get the text of the reply
axios.post('/messages/api/reply', {
memberFirstName: Cookies.get('first_name'),
memberId: Cookies.get('id'),
conversationId: conversationId,
reply: replyText
})
.then(function(res) {
if (res.status === 201) {
const reply = res.data.reply
messagesArray.push(reply)
const replyRow = (copy) => {
return `
<div class="col-md-6 col-md-offset-3" id="messageList">
<div class="well">
<div align="left">
<div style="float: left">${copy.from}: <b>${copy.message}</b></div>
<div style="float: right">Unread</div>
<div style="clear: both"></div>
</div>
</div>
</div>
`
}
if (messagesArray.length === 2) { // If this is the first reply done without refreshing the page, run this block
const copy = messagesArray[1]
replySection = replyRow(copy)
} else if (messagesArray.length > 2) { // If the user decides to send more than one reply without refreshing the page, run this block
const copy = messagesArray[messagesArray.length - 1]
replySection += replyRow(copy)
}
document.getElementById('replyId').innerHTML = replySection
document.getElementById('replyMessage').value = ' '
} else {
window.alert("Error")
}
})
}
window.addEventListener('load', () => {
const url = window.location.pathname.split('/')
if (url[1] === 'conversation' && url[2] === conversationId) {
axios.get(`/conversation/api/${conversationId}`).then((res) => {
messagesArray.push(res.data.messages)
let messageList = `<center>`;
messagesArray[0].map((message) => {
messageList += `
<div class="col-md-6 col-md-offset-3" id="messageList">
<div class="well">
<div align="left">`
message.unread ? (
messageList += `
<div style="float: left">${message.from}: <b>${message.message}</b></div>
<div style="float: right">Unread</div>
<div style="clear: both"></div>
`
) : (
messageList += `
<div style="float: left">${message.from}: ${message.message}</div>
<div style="float: right">Read</div>
<div style="clear: both"></div>
`
)
messageList += `</div></div></div>`;
})
const reply = `
<div id="contactForm">
<div class="form-group col-md-6 col-md-offset-3">
<center>
<textarea class="form-control" id="replyMessage" rows="5" cols="10"></textarea>
<br />
<button class="btn btn-primary" onclick="sendReply()">Send</button>
</center>
</div>
</div>
`;
messageList += `<div id="replyId"></div>`; // The reply goes here
messageList += `</center>`;
htmlOutput += messageList + reply
document.getElementById('my-app').innerHTML = htmlOutput;
})
} else if (url[1] === 'users' && url[3] === 'about') {
}
})
答案 0 :(得分:1)
是的,你可以使用Vanilla JS做到这一点。你可以通过多种方式实现这一目标,但这是我推荐的。
现在,由于您要在页面加载时填充消息,请在页面上调用该函数,如:
window.addEventListener('load', () => {
//your new function
getConversationAndPopulateList();
});
由于您已经有一个sendReply函数进行后调用以发送消息,因此只需修改它以在成功发送回复后注册回调。
const sendReply(cb) => {
const replyTxt = ...
axios.post(post_url, { ... })
.then(function(res) {
if (res.status === 201) {cb();}
});
}
现在你要做的就是当你调用sendReply函数时,这个函数由用户动作触发,只需调用回调中的getConverstion函数,或者如果适合你就可以返回一个promise。
sendReply(()=>{getConversationAndPopulateList();});
// and now after evry sent message your conversations will repopulate
或者更好的是,你可以通过添加参数并调用它来使senReply函数更加单一地负责。
sendReply(replyText,()=>{getConversationAndPopulateList();});
答案 1 :(得分:0)
为什么不将消息存储到数组中?当您在then
时,只需push
新数组中的结果?
我认为这可以胜任,如果它不刷新该部分,你仍然可以在你的选择器上使用appendChild()
,这将在该部分的末尾添加内容