この記事では、Webオンラインチャットを実装するためのVueの具体的なコードを参考までに紹介します。具体的な内容は次のとおりです。 最終的な効果実装プロセス無限スクロールフォームの実装については、以前にも紹介したので、ここでは繰り返しません。よくわからない場合は、前のドキュメントのポータルから確認できます。 リアルタイムオンラインチャットの主な機能
さっそくコードを見てみましょう バックエンドの戻りデータ形式すべての設計と機能実装はデータに基づいていると思うので、まずはバックエンドから返されるデータ形式を見てみましょう。 { "code": 200, // 応答コード "msg": "OK", // 応答メッセージ "total": 1, "sysTime": "2020-12-16 15:23:27", // システム応答時間 "data": [{ "avatar": "", // ユーザーアバター "content": "{\"type\":\"txt\",\"msg\":\"こんにちは! \"}", // メッセージの内容"isRead": 0, // 既読ですか? "isOneself": 0, // 自分から送信されたメッセージですか? 0 は未読、1 は既読"msgId": 10, // メッセージ ID、重複排除に使用"nickName": "碧海燕鱼", // ユーザーのニックネーム"userCode": "202012162030202232" // ユーザー コード}] } ここで注目すべきは、コンテンツ フィールドは JSON 形式の文字列データを返すことであり、コンテンツの形式は次のようになります。 // テキストメッセージ { "タイプ": "txt", "msg":"Hello" //メッセージの内容} // 画像メッセージ { "タイプ": "画像", "url": "画像アドレス", "拡張子":"jpg", "幅":360、//幅"高さ":480、//高さ"サイズ": 388245 } // ビデオメッセージ { 「タイプ」: 'ビデオ', 「URL」: "http://nimtest.nos.netease.com/cbc500e8-e19c-4b0f-834b-c32d4dc1075e", "拡張子":"mp4", "幅":360、//幅"高さ":480、//高さ"サイズ": 388245 } // 場所メッセージ { "タイプ": "ローカル", "address":"No. 599, Wangshang Road, Hangzhou, Zhejiang, China", //地理的位置 "longitude":120.1908686708565, // 経度 "latitude":30.18704515647036 // 緯度} HTMLコード <テンプレート> <Modal title="オンラインコミュニケーション" v-model="chatVisible" ドラッグ可能 フッターを非表示 :width="580" @on-cancel="キャンセル"> <div class="チャット"> <div class="チャットメッセージ本文" id="チャットフォーム" @scroll="スクロール" > <スピンv-if="読み込み中"> <アイコン type="ios-loading" size=18 class="spin-icon-load"></アイコン> </スピン> <div dis-hover v-for="(item,index) in data" :key="index" class="メッセージカード"> <div :class="item.isOneself == 1?'メッセージ行右':'メッセージ行左'"> <img :src="item.avatar?item.avatar:defualtアバター" 高さ="35" 幅="35" > <div class="メッセージコンテンツ"> <div :style="item.isOneself == 1?'text-align:right;display: flex;flex-direction:row-reverse':''"> {{item.ニックネーム}} <span class="メッセージ時間"> {{item.createTime}} </span> </div> <div class="メッセージ本文"> {{item.content.msg}} </div> </div> </div> </div> </div> <入力 v-model="フォーム.msg" タイプ="テキストエリア" スタイル="margin:10px 0;" placeholder="もっと積極的に行動すれば、世界はもっと広がります!" :行数="4" /> </div> <div class="footer-btn"> <Button @click="cancel" type="text">キャンセル</Button> <Button type="primary" @click="sendMsg">送信</Button> </div> </モーダル> </テンプレート> 注意:自分と他人が送信したメッセージの表示スタイルは異なるため、isOneself フィールドを使用して表示スタイルを区別する必要があります。 JavaScript コード <スクリプト> "@/api/index" から {listMsg,sendMsg } をインポートします。 エクスポートデフォルト{ 名前:「チャット」、 小道具: { 価値: { タイプ: ブール値、 デフォルト: false } }, データ() { 戻る { チャット可視:this.value、 読み込み中:false、 defualtAvatar:require('../../assets/defult-avatar.svg'), // バックエンドはデフォルトのアバターを返しません。注: ローカルファイル data:[] に動的にアクセスするには、require リクエストメソッドが必要です。 distincData:[], // メッセージ重複排除配列 offsetMax:0, // 最大オフセット、現在の最大 ID を記録し、将来スケジュールされた時間にデータをポーリングするたびにこの ID より大きいデータのみを取得します offsetMin:0, // 最小オフセット、現在の最小 ID を記録し、上にスライドするたびにこの ID より大きいデータのみを取得します searchForm:{ // データが取得または初めて読み込まれるたびに送信されるフォームデータ pageNumber: 1, ページサイズ: 20 }, form:{ // データを送信するフォームコンテンツ:"", メッセージ:"" }, timerSwitch:0 // タイマースイッチ、デフォルトでは閉じています}; }, メソッド: { 初期化(){ }, loadMsg(){ // デフォルトではフォームが開き、データのページが読み込まれます。フォームは一定期間に 1 回実行されます。let that = this; this.searchForm.offsetMax = this.offsetMax; listMsg(this.searchForm).then(res=>{ (res.code == 200)の場合{ res.data.forEach(e => { // 最大オフセットをマークします if (that.offsetMax < e.msgId) { that.offsetMax = e.msgId; } JSON を解析します。 that.data.unshift(e) that.distincData.push(e.msgId); // 最大オフセットをマークします。バックエンドから返されるデータは逆順なので、最後の ID が最新です。that.offsetMin = e.msgId; }); // データの読み込みが完了すると、スクロール バーがフォームの一番下までスクロールします。this.scrollToBottom(); } }); }, show(){ //フォームを開いてデータを初期化します //データを初期化します this.data = []; this.distincData = []; this.offsetMax = 0; this.offsetMin = 0; this.searchForm.pageNumber = 1; this.searchForm.pageSize = 20; this.form = { コンテンツ:""、 メッセージ:"" }; このメソッドは、 this.chatVisible = true; // タイマーをオンにします this.timerSwitch = 1; これを再ロードします。 }, sendMsg(){ // メッセージを送信 if(!this.form.msg){ this.$Message.warning("空のメッセージを送信できません"); 戻る; } let content = { // メッセージ本文をカプセル化 type:"txt", メッセージ:このフォームのメッセージ }; this.form.content = JSON.stringify(content); sendOrderMsg(this.form).then(res=>{ (res.code == 200)の場合{ データを JSON にパースします。 this.data.push(res.data) このフォームのmsg=""; this.distincData.push(res.data.msgId); スクロールダウン // メッセージを送信すると、現在のメッセージのみが返されます。相手側がすでにメッセージを送信している可能性があるため、オフセットは変更されません。} }); }, scrollToBottom(){ //フォームの一番下までスクロールします this.$nextTick(()=>{ チャットフォームを document.getElementById("チャットフォーム"); チャットフォームのスクロールトップ = チャットフォームのスクロール高さ; }); }, // 一番上までスクロールし、ページング パラメータに従って履歴データを取得します。オフセットマークを変更する必要はありませんが、再スクロールを判断する必要があります(){ チャットフォームを document.getElementById("チャットフォーム"); scrollTop を chatform.scrollTop とします。 スクロールトップ == 0 の場合 this.loading = true; です。 that = this とする; this.searchForm.offsetMin = this.offsetMin; this.searchForm.offsetMax = ""; listMsgByOrder(this.searchForm).then(res=>{ this.loading = false; です。 (res.code == 200)の場合{ res.data.forEach(e => { if (that.distincData.indexOf(e.msgId) < 0) { JSON を解析します。 that.data.unshift(e); that.distincData.push(e.msgId); // 最小オフセットを変更する if (that.offsetMin > e.msgId) { that.offsetMin = e.msgId; } } }); } }); } }, リロードデータ(){ // タイマースイッチがオンかどうかを判断します。オンの場合はタイマーを実行します。if(this.timerSwitch){ タイムアウトを設定する(() => { パラメータを {} とします。 パラメータ.ページ番号 = 1; パラメータ.pageSize = 20; パラメータのオフセットMax = this.offsetMax; that = this とする; listMsgByOrder(params).then(res=>{ (res.code == 200)の場合{ res.data.forEach(e => { // 最大オフセットを変更し、重複チェックの前に配置して、現在のメッセージがメッセージリストに追加されるのを防ぎますが、オフセット値はそこにありません if (that.offsetMax < e.msgId) { that.offsetMax = e.msgId; } if (that.distincData.indexOf(e.msgId) < 0) { JSON を解析します。 that.data.push(e) that.distincData.push(e.msgId); // 新しいメッセージを受信し、高さを決定します。現在のスクロール バーの高さが下から 100 未満の場合、一番下までスライドします。let chatform = document.getElementById("chatform"); ギャップをchatform.scrollHeight -chatform.scrollTopとします。 if(ギャップ >0 && ギャップ < 400){ スクロールダウン } } }); that.reloadData(); } }); },1000*2); } }, cancel(){ // フォームを閉じるには、プロンプトタスクスイッチもオフにする必要があります。 this.chatVisible = false; this.timerSwitch = 0; } }, マウント() { } }; </スクリプト> CSSコード <スタイル lang="less"> 。メッセージ { 高さ: 350ピクセル; } .ivu-card-body { パディング:5px; } .ivu-modal-body{ パディング: 0px 16px 16px 16px; } .チャットメッセージ本文{ 背景色:#F8F8F6; 幅:545px; 高さ: 350ピクセル; オーバーフロー:自動; } .メッセージカード{ マージン:5px; } .メッセージ行左 { ディスプレイ: フレックス; flex-direction:行; } .メッセージ行右 { ディスプレイ: フレックス; flex-direction:行の反転; } .メッセージコンテンツ{ マージン:-5px 5px 5px 5px; ディスプレイ: フレックス; flex-direction:列; } .メッセージ本文{ 境界線:1px 実線 #D9DAD9; パディング:5px; 境界線の半径:3px; 背景色:#FFF; } .メッセージ時間{ マージン:0 5px; フォントサイズ:5px; 色:#D9DAD9; } .footer-btn { フロート:右; 下部マージン: 5px; } .スピンアイコンロード{ アニメーション:ani-spin 1s 線形無限; } @keyframes アニスピン{ フォーム{transform:rotate(0deg);} 50% {変換: 回転(180度);} {transform: rotate(360deg);} へ } </スタイル> 以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: Centos での TCPWrappers アクセス制御の実装
>>: MySQL は、元のデータと同じデータがある場合、更新ステートメントを再度実行しますか?
目次序文準備する要約する継承方法プロトタイプ継承プロトタイプチェーン継承コンストラクタの借用(クラス...
目次1. データベース操作1.1 データベースの表示1.2 データベースを作成する1.3 データベー...
目次vモデル.sync微妙な違い機能シナリオを要約します。 vモデル <!--親コンポーネント...
以前にインストールされたバージョンのデータベースをアンインストールする方法については、この記事を参照...
通常、クリック イベントは、メッセージ リマインダーのさまざまな状況に分割されます。これらが処理され...
この記事では、ドラッグ可能なモーダルボックスを実装するためのJavaScriptの具体的なコードを参...
簡単に言うと、今日は Gitlab-CI を使用してリモート サーバーに自動的にデプロイする方法につ...
目次レイアウト部分: <div id="アプリ"> <p>...
序文現在の JavaScript には列挙の概念がありません。一部のシナリオでは、列挙を使用するとデ...
この記事では主にvue-routerのmatchedをベースにしたbreadcrumb機能を紹介し、...
テーブル ヘッダーが固定されている場合は、それを 2 つのテーブルに分割する必要があります。1 つの...
Mysql8.0.12 解凍版のインストール方法をテストしましたので、ご参考までに1. ダウンロー...
この記事では、参考までに、Navicat for MySql の CSV ファイルのビジュアルインポ...
方法は2つあります: 1. サービス方法ファイアウォールのステータスを確認します。 [root@ce...
たくさんのチュートリアルを読みましたが、うまくインストールできませんでした。しばらく試行錯誤した後、...