Vue realisiert Web-Online-Chat-Funktion

Vue realisiert Web-Online-Chat-Funktion

In diesem Artikelbeispiel wird der spezifische Code von Vue zur Implementierung eines Online-Chats im Web zu Ihrer Information geteilt. Der spezifische Inhalt ist wie folgt

Der endgültige Effekt

Implementierungsprozess

Die Implementierung des Formulars mit unendlichem Scrollen wurde bereits vorgestellt, daher werde ich sie hier nicht wiederholen. Wenn Sie sich nicht sicher sind, können Sie dies über das Portal im vorherigen Dokument überprüfen.

Hauptfunktionen des Echtzeit-Online-Chats

  • Scrollen Sie zum oberen Rand des Zwei-Tage-Fensters, um historische und weitere Informationen automatisch zu laden. Beim Laden der Daten muss eine Ladeanimation angezeigt werden.
  • Beim Senden einer Nachricht gleitet die Bildlaufleiste automatisch an den unteren Rand des Fensters und die von Ihnen gesendete Nachricht wird im Chatfenster angezeigt.
  • Wenn Sie eine Nachricht von jemand anderem empfangen, müssen Sie die Position der Bildlaufleiste im Fenster bestimmen. Wenn die Nachricht innerhalb eines bestimmten Bereichs vom unteren Rand empfangen wird, muss sie automatisch an den unteren Rand des Fensters verschoben werden.
  • Die gesendeten und empfangenen Nachrichten können im Chatstatus nicht wiederholt angezeigt werden;
  • Die gesendeten und empfangenen Nachrichten müssen im Chatfenster in umgekehrter Reihenfolge angezeigt werden, d. h. die Nachricht weiter unten im Fenster ist die neueste Nachricht.
  • Am besten ist es, zur Autorisierung eine lange Verbindung mit dem Backend über WebSocket herzustellen. Wenn eine neue Nachricht eingeht, sendet das Backend die Nachricht aktiv an das Frontend. Hier stellen wir hauptsächlich die Idee vor, das Chat-Fenster im Frontend zu implementieren, und erweitern den WebSocket-Teil nicht. Es wird einfach durch Timer-Polling implementiert.

Kommen wir ohne weitere Umschweife direkt zum Code

Backend-Rückgabedatenformat

Ich denke, dass alle Designs und funktionalen Implementierungen auf Daten basieren. Schauen wir uns also zunächst das vom Backend zurückgegebene Datenformat an:

{
 "code": 200, // Antwortcode "msg": "OK", // Antwortnachricht "total": 1, 
 "sysTime": "2020-12-16 15:23:27", // Systemantwortzeit "data": [{
  "Avatar": "", // Benutzeravatar "Inhalt": "{\"Typ\":\"txt\",\"msg\":\"Hallo! \"}", // Nachrichteninhalt"isRead": 0, // wurde es gelesen? "isOneself": 0, // ist es eine von Ihnen selbst gesendete Nachricht? 0 für nein, 1 für ja"msgId": 10, // Nachrichten-ID, wird für die Deduplizierung verwendet"nickName": "碧海燕鱼", // Benutzer-Spitzname"userCode": "202012162030202232" // Benutzercode}]
}

Hierbei ist zu beachten, dass das Inhaltsfeld Zeichenfolgendaten im JSON-Format zurückgibt und das Inhaltsformat wie folgt ist:

// Textnachricht {
  "Typ": "txt",
  "msg":"Hallo" //Nachrichteninhalt}
// Bildnachricht {
  "Typ": "img",
  "url": "Bildadresse",
  "ext":"jpg",
  "Breite": 360, //Breite"Höhe": 480, //Höhe"Größe": 388245
}
// Videobotschaft {
  "Typ": "Video",
  "URL": "http://nimtest.nos.netease.com/cbc500e8-e19c-4b0f-834b-c32d4dc1075e",
  "ext":"mp4",
  "Breite": 360, //Breite"Höhe": 480, //Höhe"Größe": 388245
}
// Standortnachricht {
  "Typ": "lokal",
  "Adresse": "Nr. 599, Wangshang Road, Hangzhou, Zhejiang, China", // Geografische Lage "Längengrad": 120.1908686708565, // Längengrad "Breitengrad": 30.18704515647036 // Breitengrad}

HTML Code

<Vorlage>
  <Modal title="Online-Kommunikation" v-model="chatVisible"
   verschiebbar
   Fußzeile ausblenden
   :width="580" @on-cancel="abbrechen">
   <div Klasse="Chat">
     <div Klasse="chat-message-body" id="Chatformular" @scroll="scrollen"
      >
      <Drehen v-if="wird geladen">
        <Symboltyp="ios-loading" Größe=18 Klasse="spin-icon-load"></Symbol>
      </Drehen>
        <div dis-hover v-for="(Element, Index) in Daten"
         :Schlüssel="index" Klasse="Nachrichtenkarte">
         <div :class="item.isOneself == 1?'message-row-right':'message-row-left'">
           <img:src="item.avatar?item.avatar:defualtAvatar" 
            Höhe="35" Breite="35" >
            <div Klasse="Nachrichteninhalt"> 
              <div :style="item.isOneself == 1?'text-align:right;display: flex;flex-direction:row-reverse':''">
                {{item.nickName}}
                <span class="Nachrichtenzeit">
                   {{item.createTime}}</span>
                </div>
              <div Klasse="Nachrichtentext">
                {{item.content.msg}}
                </div>
             </div> 
          </div>
         </div>
      </div>
        <Eingabe
        v-model="form.msg"
        Typ="Textbereich"
        Stil="Rand:10px 0;"
        Platzhalter="Seien Sie proaktiver, die Welt wird größer!"
        :Zeilen="4"
      />
     </div>
     <div Klasse="footer-btn">
        <Button @click="cancel" type="text">Abbrechen</Button>
        <Button type="primary" @click="sendMsg">Senden</Button>
      </div>
  </Modal>
</Vorlage>

Hinweis: Die Anzeigestile der von Ihnen und anderen gesendeten Nachrichten sind unterschiedlich. Daher müssen Sie das Feld „isOneself“ verwenden, um die Anzeigestile zu unterscheiden.

JavaScript-Code

<Skript>
importiere {listMsg,sendMsg } von "@/api/index";
Standard exportieren {
  Name: "Chat",
  Requisiten: {
    Wert: {
      Typ: Boolean,
      Standard: false
    }
  },
  Daten() {
    zurückkehren {
      chatVisible:dieser.Wert,
      wird geladen:false,
      defualtAvatar:require('../../assets/defult-avatar.svg'), // Das Backend gibt den Standardavatar nicht zurück. Hinweis: Für den dynamischen Zugriff auf lokale Dateien ist die Anforderungsmethode require erforderlich data:[],
      distincData:[], // Array zur Nachrichtendeduplizierung offsetMax:0, // maximaler Offset, zeichnet die aktuelle maximale ID auf und holt bei jedem Datenabruf zu einem geplanten Zeitpunkt in der Zukunft nur Daten, die größer als diese ID sind offsetMin:0, // minimaler Offset, zeichnet die aktuelle minimale ID auf und holt bei jedem Hochschieben nur Daten, die größer als diese ID sind searchForm:{ // Formulardaten werden jedes Mal übermittelt, wenn Daten zum ersten Mal abgerufen oder geladen werden pageNumber: 1,
        Seitengröße: 20
      },
      form:{ // Daten senden, um Datenformularinhalt zu übermitteln:"",
        Nachricht:""
      },
      timerSwitch:0 // Zeitschalter, standardmäßig geschlossen};
  },
  Methoden: {
    init(){
      
    },
    loadMsg(){ // Das Formular wird geöffnet und lädt standardmäßig eine Seite mit Daten. Das Formular wird einmal in einem bestimmten Zeitraum ausgeführt. let that = this;
      dieses.searchForm.offsetMax = dieses.offsetMax;
      listMsg(diese.Suchform).then(res=>{
        wenn (res.code == 200) {
          res.data.forEach(e => {
            // Markiere den maximalen Offset, wenn (that.offsetMax < e.msgId) {
                das.offsetMax = e.msgId;
            }
            e.Inhalt = JSON.parse(e.Inhalt);
            dass.data.unshift(e)
            das.distincData.push(e.msgId);
            // Markieren Sie den maximalen Offset. Die vom Backend zurückgegebenen Daten sind in umgekehrter Reihenfolge, sodass die letzte ID die neueste ist that.offsetMin = e.msgId;
           });
          // Nachdem das Laden der Daten abgeschlossen ist, scrollt die Bildlaufleiste zum unteren Rand des Formulars this.scrollToBottom();
        }
      });
       
        
    },
    show(){ //Formular öffnen und Daten initialisieren //Daten initialisieren this.data = [];
      dies.distincData = [];
      dies.offsetMax = 0;
      dies.offsetMin = 0;
      this.searchForm.pageNumber = 1;
      this.searchForm.pageSize = 20;
      dieses.Formular = {
        Inhalt:"",
        Nachricht:""
      };
      dies.loadMsg();
      this.chatVisible = wahr;
      // Schalte den Timer ein this.timerSwitch = 1;
      dies.reloadData();
    },
    sendMsg(){ // Nachricht senden if(!this.form.msg){
         this.$Message.warning("Kann keine leere Nachricht senden");
        zurückkehren;
      }
      let content = { // Nachrichtentext einkapseln type:"txt",
        msg:dieses.Formular.msg
      }; 
      dieses.Formular.Inhalt = JSON.stringify(Inhalt);
      sendOrderMsg(dieses.Formular).then(res=>{
        wenn (res.code == 200) {
          res.data.content = JSON.parse(res.data.content);
          diese.Daten.push(res.Daten)
          dieses.form.msg="";
          diese.distincData.push(res.data.msgId);
          dies.scrollToBottom();
          // Beim Senden einer Nachricht wird nur die aktuelle Nachricht zurückgegeben. Die andere Partei hat die Nachricht möglicherweise bereits gesendet, sodass der Offset nicht geändert wird.}
      });
    },
    scrollToBottom(){ //Zum Ende des Formulars scrollen this.$nextTick(()=>{
          let chatform = document.getElementById("chatform");
          chatform.scrollTop = chatform.scrollHeight;
      });
    },
    // Nach oben scrollen und historische Daten gemäß den Paging-Parametern abrufen. Die Offset-Markierung muss nicht geändert werden, aber das erneute Scrollen muss beurteilt werden () {
      let chatform = document.getElementById("chatform");
      let scrollTop = chatform.scrollTop;
      wenn(scrollTop == 0){
        dies.wird geladen =wahr;
        lass das = dies;
        diese.searchForm.offsetMin = diese.offsetMin;
        this.searchForm.offsetMax = "";
        listMsgByOrder(diese.Suchform).dann(res=>{
           dies.wird geladen =false;
            wenn (res.code == 200) {
              res.data.forEach(e => {
                wenn (that.distincData.indexOf(e.msgId) < 0) {
                  e.Inhalt = JSON.parse(e.Inhalt);
                  dass.data.unshift(e);
                  das.distincData.push(e.msgId);
                  // Ändere den minimalen Offset, wenn (that.offsetMin > e.msgId) {
                      das.offsetMin = e.msgId;
                  }
                }
              });
            }
        });
      }
    },
   Daten neu laden(){
    // Bestimmen Sie, ob der Timer eingeschaltet ist. Wenn ja, führen Sie den Timer aus, if(this.timerSwitch){
      setzeTimeout(() => {
        lass Parameter = {};
        params.Seitennummer = 1;
        Parameter.Seitengröße = 20;
        params.offsetMax = dies.offsetMax;
        lass das = dies;
        listMsgByOrder(params).then(res=>{
          wenn (res.code == 200) {
            res.data.forEach(e => {
              // Ändere den maximalen Offset und setze ihn vor die Duplikatsprüfung, um zu verhindern, dass die aktuelle Nachricht in die Nachrichtenliste aufgenommen wird, aber der Offset-Wert nicht vorhanden ist, if (that.offsetMax < e.msgId) {
                  das.offsetMax = e.msgId;
              }
              wenn (that.distincData.indexOf(e.msgId) < 0) {
                e.Inhalt = JSON.parse(e.Inhalt);
                dass.data.push(e)
                das.distincData.push(e.msgId);
                // Neue Nachricht empfangen, Höhe bestimmen, wenn die aktuelle Höhe der Bildlaufleiste weniger als 100 vom unteren Rand beträgt, nach unten schieben let chatform = document.getElementById("chatform");
                let gap = chatform.scrollHeight -chatform.scrollTop;
                wenn(Lücke >0 && Lücke < 400){
                  dies.scrollToBottom();
                }
              }
            });
            dass.reloadData();
          }
        });
      },1000*2);
    }
    
   },
   cancel(){ // Um ​​das Formular zu schließen, müssen Sie auch den Schalter für die Eingabeaufforderungsaufgabe deaktivieren. this.chatVisible = false;
     dieser.timerSwitch = 0;
   }
  },
  montiert() {
  }
};
</Skript>

CSS Code

<style lang="less">
   .Nachricht {
        Höhe: 350px;
    }
  .ivu-Kartenkörper {
    Polsterung: 5px;
  }
  .ivu-modal-body{
    Polsterung: 0px 16px 16px 16px;
  }
  .chat-message-body {
   Hintergrundfarbe: #F8F8F6;
   Breite: 545px;
   Höhe: 350px;
   Überlauf: automatisch;
  }
  .Nachrichtenkarte {
   Rand: 5px;
  }
  .message-row-left {
   Anzeige: Flex;
   Flex-Richtung: Zeile;
  }
  .message-row-right {
   Anzeige: Flex;
   Flex-Richtung: Zeile umkehren;
  }
  .Nachrichteninhalt {
    Rand: -5px 5px 5px 5px;
    Anzeige: Flex;
    Flex-Richtung:Spalte;
  }
  .Nachrichtentext {
    Rand: 1px durchgezogen #D9DAD9;
    Polsterung: 5px;
    Rahmenradius: 3px;
    Hintergrundfarbe:#FFF;
  }
  .Nachrichtenzeit {
    Rand: 0,5px;
    Schriftgröße: 5px;
    Farbe: #D9DAD9;
  }
  .footer-btn {
    schweben: rechts;
    Rand unten: 5px;
  }
  .spin-icon-laden {
    Animation: Ani-Spin 1 s linear unendlich;
  }
  @keyframes ani-spin{
    Form {transform:rotate(0deg);}
    50 % {transform: drehen(180 Grad);}
    zu {transformieren: drehen(360deg);}
  }
</Stil>

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird.

Das könnte Sie auch interessieren:
  • Vue + Express + Socket realisiert Chat-Funktion
  • Vue implementiert Chat-Schnittstelle
  • Das Vue + Webterminal imitiert die Chatroom-Funktion der WeChat-Webversion
  • Vue.js imitiert das WeChat-Chatfenster, um Komponentenfunktionen anzuzeigen
  • Vue + socket.io implementiert einen einfachen Chatroom-Beispielcode
  • Eine Single-Page-Anwendungsfunktion, die mobiles QQ basierend auf Vue2 imitiert (Zugriff auf Chatbot)
  • So verwenden Sie RongCloud IM, um die Chat-Funktion im Vue Cli 3-Projekt zu implementieren
  • Beispiel einer von Vue implementierten WeChat-Roboter-Chat-Funktion [mit Quellcode-Download]
  • Mehrpersonen-Online-Chatroom basierend auf Vue und WebSocket
  • Vue+SSH-Framework zur Realisierung von Online-Chat

<<:  Implementierung der TCPWrappers-Zugriffskontrolle in Centos

>>:  Führt MySQL die Aktualisierungsanweisung erneut aus, wenn sie dieselben Daten enthält wie die ursprüngliche?

Artikel empfehlen

Neun erweiterte Methoden zur Deduplizierung von JS-Arrays (erprobt und effektiv)

Vorwort Die allgemeinen Methoden sind hier nicht ...

So verhindern Sie, dass Website-Inhalte in Suchmaschinen aufgenommen werden

Normalerweise besteht das Ziel beim Erstellen ein...

So unterstützen Sie vollständiges Unicode in MySQL/MariaDB

Inhaltsverzeichnis Einführung in utf8mb4 Fehler b...

Unterschied zwischen HTML ReadOnly und Enabled

Das Textfeld mit dem ReadOnly-Attribut wird auf de...

Docker stop stoppt/remove löscht alle Container

In diesem Artikel wird hauptsächlich das Stoppen/...

So finden Sie identische Dateien in Linux

Während der Nutzung des Computers entsteht im Sys...

So deinstallieren Sie IIS7-Web- und FTP-Dienste in Win7 vollständig

Nachdem ich gestern die PHP-Entwicklungsumgebung ...

So erstellen Sie ein ELK-Protokollsystem basierend auf Docker

Hintergrundanforderungen: Mit zunehmender Größe d...

Implementierung der Nginx-Konfiguration des lokalen Image-Servers

Inhaltsverzeichnis 1. Einführung in Nginx 2. Aufb...

Natives JS zum Erzielen digitaler Tisch-Spezialeffekte

Dieser Artikel beschreibt einen Digitaluhreffekt,...

Beispielcode zur Implementierung eines einfachen ListViews-Effekts in HTML

HTML zum Erreichen eines einfachen ListViews-Effe...

Beispielanalyse der Verwendung von Dockerfile-Textdateien

Dockerfile ist eine Textdatei, die zum Erstellen ...