【问题标题】:Update a section of a page after a post request在发布请求后更新页面的一部分
【发布时间】:2018-02-14 10:22:23
【问题描述】:

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

  }
})

【问题讨论】:

  • 更新:我想通了。我只是在html代码的底部放置了一个带有id的空白div标签,然后在回复的承诺中使用document.getElementById('replyId').innerHTML定位id

标签: javascript post get axios


【解决方案1】:

是的,您可以使用 Vanilla JS 做到这一点。您可以通过多种方式实现这一点,但这是我的建议。

  1. 创建一个简单的 getConversation 函数,仅负责进行 post 调用并填充 HTML 模板或列表 (UL)
  2. 现在,既然您想在页面加载时填充消息,请在页面准备就绪时调用该函数:

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

    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
    

或者更好的是,您可以通过添加参数并调用它来使 senReply 函数更加单一地负责。

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

【讨论】:

  • 我的想法也是如此。感谢您的详细回复!
【解决方案2】:

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

我认为这可以完成这项工作,如果它不刷新部分,您仍然可以在选择器处使用appendChild(),它将在部分末尾添加内容

【讨论】:

    猜你喜欢
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 2021-11-16
    • 2018-12-18
    • 1970-01-01
    相关资源
    最近更新 更多