简体   繁体   English

我如何只呈现更新的统计数据 - websockets

[英]How do I only render the updated stat - websockets

right now the entire div re-renders, but I am searching for a way to only re-render the updated statistic现在整个 div 重新渲染,但我正在寻找一种只重新渲染更新的统计信息的方法

these are parts of what I have now这些是我现在拥有的部分

updatestats.js 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 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统计数据.pug

body
h1 Cases by country
div#overview

So if I only update the country Belgium I only want that statistic to be changed.因此,如果我只更新国家比利时,我只希望更改该统计数据。 Now everything seems to reload现在一切似乎都重新加载

What I meant with my suggestion is to keep te communication of data between client and server strictly in the sockets.我的建议是在 sockets 中严格保持客户端和服务器之间的数据通信。 Meaning when one user updates 1 value on their end, that value will be send to the server and stored.这意味着当一个用户更新 1 个值时,该值将被发送到服务器并存储。 After the server finished storing the value, that same value will be sent to all other clients.在服务器完成存储该值后,该相同的值将被发送到所有其他客户端。 This way you only send and receive the parts that have been changed without having to download everything on every change.这样,您只需发送和接收已更改的部分,而无需在每次更改时下载所有内容。

I might not be able to write the code exactly as it should be as I have limited experience with Primus.js and know little about your backend.我可能无法完全按照应有的方式编写代码,因为我对 Primus.js 的经验有限,并且对您的后端知之甚少。

But I would think that your frontend part would look something like this.但我认为你的前端部分看起来像这样。 In the example below I've removed the fetch function from the click event.在下面的示例中,我从click事件中删除了fetch function。 Instead send the changed data to the server which should handle those expensive tasks.而是将更改的数据发送到应该处理那些昂贵任务的服务器。

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);

});

Now the server should get a message that one of the clients has updated some of the data.现在服务器应该收到一条消息,其中一个客户端已经更新了一些数据。 And should do something with that data, like storing it and letting the other clients know that this piece of data has been updated.并且应该对这些数据做一些事情,比如存储它并让其他客户端知道这条数据已经更新。

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);

  }
});

The server should now have stored the changes and broadcasted the change to all other clients.服务器现在应该已经存储了更改并将更改广播给所有其他客户端。 Now you yourself and other will receive the data that has been changed and can now render it.现在您自己和其他人将收到已更改的数据并可以渲染它。 So back to the frontend.所以回到前端。 We do the same trick as on the server by listening for the data event and check the action in the data object to figure out what to do.我们通过侦听data事件并检查数据 object 中的操作来确定要做什么,来执行与服务器上相同的技巧。

You'll need a way to figure out how to target the elements which you want to change, you could do this by having id attributes on your elements that correspond with the data.您需要一种方法来确定如何定位要更改的元素,您可以通过在与数据对应的元素上设置 id 属性来做到这一点。 So for example you want to change the 'Belgium' paragraph then it would come in handy if there is a way to recognize it.因此,例如,您想更改“比利时”段落,那么如果有办法识别它,它就会派上用场。 I won't go into that too much but just create something simple which might do the trick.我不会 go 太多,而只是创建一些简单的东西可能会奏效。

In the HTML example below I've given the paragraph an id.在下面的 HTML 示例中,我为段落指定了一个 ID。 This id is the same as the country value that you want to update.此 id 与您要更新的国家/地区值相同。 This is a unique identifier to find the element that you want to update.这是查找要更新的元素的唯一标识符。 Or even create if it is not there.或者甚至创建如果它不存在。

The JavaScript example after that receives the data from the server through the sockets and checks the action.之后的 JavaScript 示例通过 sockets 从服务器接收数据并检查操作。 This is the same data that we send to the server, but only now when everybody received we do something with it.这与我们发送到服务器的数据相同,但只是现在每个人都收到了,我们才对其进行处理。

I've written a function that will update the data in your HTML.我写了一个 function 将更新 HTML 中的数据。 It will check for an element with the id that matches the country and updates the textContent property accordingly.它将检查 id 与国家/地区匹配的元素并相应地更新textContent属性。 This is almost the same as using document.createTextNode but with less steps.这与使用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}`;
  }
}

I hope that this is what you are looking for and / or is helpful for what you are trying to create.我希望这是您正在寻找的内容和/或对您尝试创建的内容有所帮助。 I want to say again that this is an example of how it could work and has not been tested on my end.我想再说一遍,这是它如何工作的一个例子,并且还没有经过我的测试。

If you have any questions or I have been unclear, then please don't hesitate to ask.如果您有任何问题或我不清楚,请不要犹豫,问。

To elaborate @EmielZuurbier's suggestion in the comment, please try the following code.要在评论中详细说明@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');

})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM