在发布请求后更新页面的一部分

时间:2018-02-14 10:22:24

标签: javascript post get axios

在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') {

  }
})

2 个答案:

答案 0 :(得分:1)

是的,你可以使用Vanilla JS做到这一点。你可以通过多种方式实现这一目标,但这是我推荐的。

  1. 创建一个简单的getConversation函数,仅负责进行调用并填充HTML模板或列表(UL)
  2. 现在,由于您要在页面加载时填充消息,请在页面上调用该函数,如:

    window.addEventListener('load', () => {
        //your new function 
        getConversationAndPopulateList();
    });
    
  3. 由于您已经有一个sendReply函数进行后调用以发送消息,因此只需修改它以在成功发送回复后注册回调。

    const sendReply(cb) => {
       const replyTxt  = ...
       axios.post(post_url, { ... })
          .then(function(res) {
                 if (res.status === 201) {cb();}
           });
    }
    
  4. 现在你要做的就是当你调用sendReply函数时,这个函数由用户动作触发,只需调用回调中的getConverstion函数,或者如果适合你就可以返回一个promise。

     sendReply(()=>{getConversationAndPopulateList();});
     // and now after evry sent message your conversations will repopulate
    
  5. 或者更好的是,你可以通过添加参数并调用它来使senReply函数更加单一地负责。

    sendReply(replyText,()=>{getConversationAndPopulateList();});
    

答案 1 :(得分:0)

为什么不将消息存储到数组中?当您在then时,只需push新数组中的结果?

我认为这可以胜任,如果它不刷新该部分,你仍然可以在你的选择器上使用appendChild(),这将在该部分的末尾添加内容