【问题标题】:How do I only render the updated stat - websockets我如何只呈现更新的统计数据 - websockets
【发布时间】:2020-04-22 02:50:29
【问题描述】:

现在整个 div 重新渲染,但我正在寻找一种只重新渲染更新的统计信息的方法

这些是我现在拥有的部分

updatestats.js

document.querySelector("#submit").addEventListener("click", function (e) {
let country = document.querySelector("#country").value
let numberCases = document.querySelector("#number").value

fetch(base_url + "/api/v1/stats/updatestats", {
    method: "put",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        "country": country,
        "numberCases": numberCases
    })
}).catch(err => {
    console.log(err);
})

primus.write({ "action": "update" })

stats.js

 primus.on("data", (json) => {
    if (json.action === "update") {
        document.querySelector("#overview").innerHTML = ""
        appendInfo()
    }
})

function appendInfo() {
    fetch(base_url + "/api/v1/stats", {
        method: "get",
        headers: {
            'Content-Type': 'application/json'
        },
    }).then(response => {
        return response.json();
    }).then(json => {
        json.data.stats.forEach(stat => {
            let country = stat.country
            let numberCases = stat.numberCases
            let p = document.createElement('p')
            let text = document.createTextNode(`${country}:   ${numberCases}`)
            p.appendChild(text)
            let overview = document.querySelector("#overview")
            overview.appendChild(p)
        })
    }).catch(err => {
        console.log(err);
    })
}


window.onload = appendInfo();

stats.pug

body
h1 Cases by country
div#overview

因此,如果我只更新比利时国家/地区,我只希望更改该统计信息。现在一切似乎都重新加载了

【问题讨论】:

  • 你试过event.preventDefault()吗?它仅在更新数据时停止页面重新加载
  • 您可以不使用 fetch 上传和下载数据,而是使用 websockets 将更改的数据发送到服务器,然后从服务器将其传递给所有其他客户端。这样,每个人都只能获得通过套接字更改的数据。从那里将您已有的数据与新收到的数据进行比较,并仅更新更改的元素。
  • @AvivLo 我在我在这里添加的最后一个 updatestats.js 行下面有 e.preventDefault() 行
  • @EmielZuurbier 你有什么例子吗,因为我知道了理论,但不知道如何在我的代码中添加它

标签: javascript node.js websocket primus


【解决方案1】:

我的建议的意思是将客户端和服务器之间的数据通信严格地保持在套接字中。这意味着当一个用户更新 1 个值时,该值将被发送到服务器并存储。在服务器完成存储该值后,该相同的值将被发送到所有其他客户端。这样,您只需发送和接收已更改的部分,而无需在每次更改时下载所有内容。

我可能无法完全按照应有的方式编写代码,因为我对 Primus.js 的经验有限,并且对您的后端知之甚少。

但我认为您的前端部分看起来像这样。在下面的示例中,我从 click 事件中删除了 fetch 函数。而是将更改的数据发送到应该处理那些昂贵任务的服务器。

const countryElement = document.querySelector("#country");
const numberCasesElement = document.querySelector("#number");
const submitButton = document.querySelector("#submit");

submitButton.addEventListener("click", function (e) {

  let data = {
    action: 'update',
    country: countryElement.value,
    numberCases: numberCasesElement.value
  };

  primus.write(data);

});

现在服务器应该收到一条消息,其中一个客户端已经更新了一些数据。并且应该对这些数据做一些事情,比如存储它并让其他客户端知道这条数据已经更新。

primus.on('data', data => {
  const { action } = data;
  if (action === 'update') {

    // Function that saves the data that the socket received.
    // saveData(data) for example.

    // Send changed data to all clients.
    primus.write(data);

  }
});

服务器现在应该已经存储了更改并将更改广播给所有其他客户端。现在您自己和其他人将收到已更改的数据并可以渲染它。所以回到前端。我们通过侦听data 事件并检查数据对象中的操作来确定要做什么来执行与服务器上相同的技巧。

您需要一种方法来确定如何定位您想要更改的元素,您可以通过在与数据对应的元素上设置 id 属性来做到这一点。因此,例如,您想更改“比利时”段落,那么如果有办法识别它,它就会派上用场。我不会过多介绍,只是创建一些简单的东西可能会奏效。

在下面的 HTML 示例中,我为段落指定了一个 ID。此 id 与您要更新的国家/地区值相同。这是查找要更新的元素的唯一标识符。如果它不存在,甚至创建。

之后的 JavaScript 示例通过套接字从服务器接收数据并检查操作。这与我们发送到服务器的数据相同,但只是现在每个人都收到了,我们才对其进行处理。

我编写了一个函数来更新 HTML 中的数据。它将检查 id 与国家/地区匹配的元素并相应地更新 textContent 属性。这与使用document.createTextNode 几乎相同,但步骤更少。

<div id="overview">
  <p id="Belgium">Belgium: 120</p>
</div>
const overview = document.querySelector("#overview");

primus.on('data', data => {
  const { action } = data;
  if (action === 'update') {
    updateInfo(data);
  }
});

function updateInfo(data) {
  const { country, numberCases } = data;

  // Select existing element with country data.
  const countryElement = overview.querySelector(`#${country}`);

  // Check if the element is already there, if not, then create it.
  // Otherwise update the values.
  if (countryElement === null) {
    const paragraph = document.createElement('p');
    paragraph.id = country;
    paragraph.textContent = `${country}: ${numberCases}`;
    overview.append(paragraph);
  } else {
    countryElement.textContent = `${country}: ${numberCases}`;
  }
}

我希望这是您正在寻找的内容和/或对您尝试创建的内容有所帮助。我想再说一遍,这是它如何工作的一个例子,我还没有经过测试。

如果您有任何问题或我不清楚,请不要犹豫。

【讨论】:

    【解决方案2】:

    要详细说明@EmielZuurbier 在评论中的建议,请尝试以下代码。

    //Client-side
    
    primus.emit('data',data);
    
    primus.on("dataUpdated", (json) => {
    
    });
    
    //Server-side
    
    primus.on('data',data =>{
    
    //process it here and then
    //send it out again
    
    
    primus.emit('dataUpdated','the data you want to send to the front end');
    
    })
    

    【讨论】:

      猜你喜欢
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 2014-01-27
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多