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

Dieser Artikel entführt Sie in die Welt der js-Datentypen und Datenstrukturen

Inhaltsverzeichnis 1. Was ist dynamische Typisier...

Beispiel für die Bereitstellung einer Laravel-Anwendung mit Docker

Das in diesem Artikel verwendete PHP-Basisimage i...

HTML-Tabellen-Tag-Tutorial (44): Tabellenkopfzeilen-Tag

<br />Um die Tabellenstruktur im Quellcode d...

Analyse des GTK-Treeview-Prinzips und der Verwendung

Die GtkTreeView-Komponente ist eine erweiterte Ko...

Erfahren Sie, wie Sie mit Webpack TypeScript-Code verpacken und kompilieren

TypeScript-Bündelung Webpack-Integration Normaler...

Analyse der Informationsarchitektur von Facebook

<br />Original: http://uicom.net/blog/?p=762...

HTML realisiert Hotel-Screening-Funktion über Formular

<!doctype html> <html xmlns="http:/...

Analyse des Unterschieds zwischen absolutem und relativem Pfad in HTML

Wie in der Abbildung gezeigt: Mit einer einzelnen ...

Mysql gibt die Methode zur Datumsbereichsextraktion an

Bei der Datenbankoperation ist der Umgang mit Dat...

Chinesische Parameterbeschreibung und Verwendungsbeispiele für ffmpeg

1. Wenn ffmpeg Videodateien überträgt, können die...

Vue+openlayer5-Methode zum Abrufen der Koordinaten des aktuellen Mauszeigers

Vorwort: Wie erhält man die Koordinaten der aktue...