我有一个带数据表的Vue页面,大约每秒钟通过一个外部服务器通过websocket接收一个json对象,并且我想在数据表<v-data-table>
中显示此事件(如果不存在或不更新)当前存在的与此新事件对应的行。
每个json对象具有完全相同的结构,类似。
{"name": "john", "sport": "football", "score": "0-0", "startTime": 1234567, "lastUpdate": 123456}
这里的问题是lastUpdate,在许多情况下,score将是唯一随时间变化的字段,但是我的数据表会将其视为新项目并将其添加到表中。
我正在使用由Set支持的数组来减轻这种情况,但是Set AFAIK比较对象本身而不是字段(或类似Java的逐个字段)。
从https://vuetifyjs.com/en/components/data-tables中我看到有一个item-key
道具,我不知道该在哪里定义和放置它。我相信,如果我可以将每个项目的ID组成为name+sport+startTime
,这将是所有事件的唯一关键金额。
例如,在我的vuetify数据表中,我具有以下数据:
| name | sport | score | startTime | lastUpdated |
----------------------------------------------|-------------|
| John | football | 0-0 | 12345678 | 123456 |
| Mark | football | 0-0 | 112458 | 122111 |
然后我收到以下事件:
{"name": "john", "sport": "football", "score": "1-0", "startTime": 1234567, "lastUpdate": 123999}
它应该使用新数据更新数据表的第一行,但它将使用此事件创建新行。
我的问题是,如果一个数据表项已经存在,如何更新它(忽略“ lastUpdate”和“ score”字段)?
我知道我可以遍历数组并进行一个一个的比较,但是我想避免这种方法,而是采用一种更为vuetify / nuxtjs的本地方法来实现。
我的vtable:
<v-data-table
:headers="headers"
:items="sportEvents"
:sort-by="sortBy">
<template v-slot:item.action="{ item }">
<v-icon small class="mr-2" @click="editItem(item)">
edit
</v-icon>
<v-icon small @click="hideItem(item)">
delete
</v-icon>
</template>
</v-data-table>
这是我的脚本代码:
<script>
import SockJS from "sockjs-client";
import Stomp from "webstomp-client";
import axios from 'axios';
export default {
name: "websocketdemo",
data() {
return {
sportEvents: [],
send_message: null,
connected: false,
headers: [
{
text: 'Home Team',
align: 'left',
sortable: false,
value: 'home',
},
{
text: 'Away Team',
align: 'left',
sortable: false,
value: 'away',
},
{
text: 'League',
value: 'league',
align: 'left',
sortable: false,
},
{ text: 'Start Time', value: 'startTime' },
{ text: 'Last Update (Seconds)', value: 'bookie.lastUpdated' },
{ text: 'Actions', value: 'action', sortable: false }
],
sortBy: 'true',
editedIndex: -1
};
},
methods: {
connect() {
this.socket = new SockJS("http://example.com/event-feed");
this.stompClient = Stomp.over(this.socket);
this.stompClient.connect(
{},
frame => {
this.connected = true;
this.stompClient.subscribe("/topic/event-feed", tick => {
let listEvents = JSON.parse(tick.body);
for(let i = 0; i < listEvents.length; i++) {
this.sportEvents.push(listEvents[i]);
}
// Filter out duplicates :: If lastUpdated value differs it is not considered a duplicated - fix this
this.sportEvents = Array.from(new Set(this.sportEvents))
});
},
error => {
console.log("Error callback");
console.log(error);
this.connected = false;
}
);
},
disconnect() {
if (this.stompClient) {
this.stompClient.disconnect();
}
this.connected = false;
},
tickleConnection() {
this.connected ? this.disconnect() : this.connect();
},
hideItem(item) {
const index = this.sportEvents.indexOf(item)
this.sportEvents.splice(index, 1);
},
editItem(item) {
var config = {
headers: { 'Content-Type': 'application/json' }
};
axios.put('http://example.com/edit/item', {
sportEventId: item.sportEventId,
amount: 10
}, config)
.then(function (response) {
alert('Item edited');
});
},
picker(index) {
return index % 2 === 0 ? 'red' : 'blue';
}
},
mounted() {
// this.connect();
},
computed: {
sportEventExists() {
return this.sportEvents.length > 0;
}
}
};
</script>