preface

When we chat on QQ, the chat records of the same minute will be displayed together. When we send messages, the sending time of each message will be accurate to the second. So how does he achieve the display of these data by minute?

Today add open source project to me on the chat messages show time, I met the question, at first not understand should be how to deal with these data, then after some thinking, and finally an implementation approach and its implementation, the implementation of next I will share with you this way of thinking and process, welcome interested developers to read this article.

Let me show you the final result:

Implementation approach

First, let me show you my data, as follows:

[{
	"createTime": "The 2020-12-21 20:58:19"."avatarSrc": "https://www.kaisir.cn/uploads/1ece3749801d4d45933ba8b31403c685touxiang.jpeg"."msgId": "121710f399b84322bdecc238199d6888"."msgText": "/ smile/"."userName": "The Amazing Programmer."."userId": "c04618bab36146e3a9d3b411e7f9eb8f"."status": false
}, {
	"createTime": "The 2020-12-21 20:58:22"."avatarSrc": "https://www.kaisir.cn/uploads/1ece3749801d4d45933ba8b31403c685touxiang.jpeg"."msgId": "121710f399b84322bdecc238199d6888"."msgText": "Anyone else?"."userName": "The Amazing Programmer."."userId": "c04618bab36146e3a9d3b411e7f9eb8f"."status": false
}, {
	"createTime": "The 2020-12-21 20:58:46"."avatarSrc": "https://www.kaisir.cn/uploads/1ece3749801d4d45933ba8b31403c685touxiang.jpeg"."msgId": "121710f399b84322bdecc238199d6888"."msgText": "Chat history, added time to send messages."."userName": "The Amazing Programmer."."userId": "c04618bab36146e3a9d3b411e7f9eb8f"."status": false
}, {
	"createTime": "The 2020-12-21 20:58:52"."avatarSrc": "https://www.kaisir.cn/uploads/1ece3749801d4d45933ba8b31403c685touxiang.jpeg"."msgId": "121710f399b84322bdecc238199d6888"."msgText": "Now it looks a lot easier."."userName": "The Amazing Programmer."."userId": "c04618bab36146e3a9d3b411e7f9eb8f"."status": false
}, {
	"createTime": "The 2020-12-21 21:35:27"."avatarSrc": "https://www.kaisir.cn/uploads/1ece3749801d4d45933ba8b31403c685touxiang.jpeg"."msgId": "121710f399b84322bdecc238199d6888"."msgText": "/ smile/"."userName": "The Amazing Programmer."."userId": "c04618bab36146e3a9d3b411e7f9eb8f"."status": false
}]
Copy the code

Observing the above data, we found that: Each message object has a createTime property, which is the time at which the message was sent. Now we need to keep only one createTime property for the same minute, and only render the object with the createTime property. That’s how you render the same minute of data together.

That’s the general idea, but let’s look at the specific idea:

  1. Declare an object namedtimeObjIn the message objectcreateTimeThe fieldYear – month – day hour: minuteDeclare a new array of message recordsfinalTextListStore processed data
  2. Iterates through the message record array to get the message record object currently iterated
  3. Of the traversed message log objectcreateTimeProperty, interceptionYear – month – day hour: minuteDeclare a variabletimeTo save the
  4. judgetimeDoes it existtimeObjIn the
  5. Delete the message record object traversed if it existscreateTimeProperty to place the message log object after the property is deletedfinalTextListIn the
  6. Otherwise it would betimePut in as a propertytimeObjIn, place the traversed message log object intactfinalTextListIn the

After processing the data, we determine at render time whether createTime exists in the current render item and render if it does.

The implementation process

Next, we take the data returned by the interface and process it in accordance with the above ideas.

Process the data returned by the interface

Res.data. messageTextList is the list of message records returned by the interface, as shown below.

// List of message contents
const messageTextList: Array<msgListType> = res.data.messageTextList;
// An array of processed message contents
const finalTextList: Array<msgListType> = [];
// Time stores objects
const timeObj: { [key: string] :boolean } = {};
// Process the list of message contents, keeping only one creation time for each minute of data
for (let i = 0; i < messageTextList.length; i++) {
    // Message object
    const messageObj = messageTextList[i];
    // Get time year - month - day: minute
    const time = (messageObj.createTime as string).substring(0.16);
    // If time already exists in timeObj, remove createTime from the current message object
    if (_.has(timeObj, time)) {
        // Remove the createTime attribute
        _.unset(messageObj, "createTime");
        // Place the message object with the createTime attribute removed into the processed message array
        finalTextList.push(messageObj);
    } else {
        // Place time as the key in timeObj
        timeObj[time] = true;
        // Put the message object into the processed message arrayfinalTextList.push(messageObj); }}// Render the message list
this.renderPage(finalTextList, {});
Copy the code

In the above code msgListType is the type definition of the message log object, has is the lodash method to determine whether the object contains an attribute, and unset is the Lodash method to remove an attribute from the object.

Handling push data

Received a data server push, we would like to news aggregation server push to the already rendered in the chat, if not the same minute news render new time, so we need to remove the current push message createTime fields, intercepting year – month – day: points to judge whether the list of records in the rendering of the news, If the createTime field is not present, render as it is, otherwise delete createTime and render as follows:

Render a single message object after receiving a new message pushed by the server
const thisSenderMessageObj: msgListType = {
    msgText: msgObj.msgText,
    avatarSrc: msgObj.avatarSrc,
    userId: msgObj.userId,
    userName: msgObj.userName,
    createTime: msgObj? .createTime };Remove the createTime object for the new message by finding the message in the message record list at the same minute as the new message
for (let i = 0; i < this.senderMessageList.length; i++) {
    const messageObj: msgListType = this.senderMessageList[i];
    // Intercepts the time when the current message is sent and the time when the new message is sent: minute to determine whether they are equal
    if(_.isEqual( messageObj.createTime? .substring(0.16),thisSenderMessageObj.createTime? .substring(0.16))) {
        // Remove the createTime attribute for the new message
        _.unset(thisSenderMessageObj, "createTime"); }}// Parse and render
this.messageParsing(thisSenderMessageObj);
Copy the code

MsgObj pushes messages to the server

To render the page

Let’s look at the rendering code for the page, as shown below, which only renders the data in the object that contains the createTime attribute

<! - message time -- > < div class = "snder - time - a panel" v - if = "item. CreateTime" > < span > {{item. CreateTime. Substring (5, 16) }}</span> </div>Copy the code

Rendering optimization

Thanks to @Leewing’s suggestion, I changed the data type directly. When rendering new data, I will compare the already rendered data each time with O(n) time complexity.

After using the idea of digging friends, the time complexity is directly reduced from O(n) to O(1)😄, the code is as follows:

<! - message time: current sending messages indicate for the first time -- > < div class = "sender - time - a panel" v - if = "index = = = 0" > < span > {{item. CreateTime. Substring (11, 16) }}</span> </div> <! On the current message and send a message time to capture moments of subtraction is greater than 1 will display time -- > < div class = "sender - time - a panel" v - else - if = "parseInt (item) createTime) the substring (11, 13) + item.createTime.substring(14, 16) ) - parseInt( senderMessageList[index - 1].createTime.substring(11, 13) + senderMessageList[index - 1].createTime.substring(14, 16) ) > 1 " > <span>{{ item.createTime.substring(11, 16) }}</span> </div>Copy the code

Implementation effect

Finally, let’s take a look at the implementation, as follows:

Let’s send another message to see what it looks like:

The project address

Code address: message-display.vue

Online experience address: chat-system

Write in the last

  • If there are any errors in this article, please correct them in the comments section. If this article helped you, please like it and follow 😊
  • This article was first published in nuggets. Reprint is prohibited without permission 💌