Vue Social(vue+express+sockete.ioはチャットで写真を送ることができる社交プラットフォームを実現する)


Vue Social
Vue Social something like QQ、weibo、weixinの前後に分離されたvue+express+sockett.ioトレーナープロジェクトの先端コードはBlogPhoneの下で、バックエンドコードはserverの下にあります。このプロジェクトがいいと思ったら、あなたのスターは私に一番いい励ましです。
内容
  • プレビュー
  • 技術スタック
  • は、機能
  • を実現しました。
  • は改善されるべきです。
  • インストール
  • 分析総括
  • プレビュー
    オンラインdemo VueSocial(pcを押してf 12を押した後に小さい問題があって、更新してすぐに良くて、resizeの触発する問題、改善することを待ちます)github住所
    最初のページ
    ログイン
    メッセージ
    雑談する
    個人情報
    ホームページ
    動態を分かち合う
    アイコンを変更
    検索ページ
    技術倉庫
  • vue:フロントエンドフレーム
  • express:バックエンドフレーム
  • socket.io:リアルタイムメッセージプッシュを実現する
  • axios:PromiseベースのHTTPライブラリが、ajax要求
  • を送信する。
  • local Strage:ブラウザローカルストレージ
  • Webpack:モジュールパッキングツール、フロントエンドプロジェクト構築ツール
  • モングース:モンゴdbのフレーム
  • better-scroll:モバイル端末(PCに対応しています)の様々なスクロールシーンのニーズを重点的に解決するプラグイン
  • 実装済み機能
  • ログイン
  • 写真共有:ローカル画像をクラウドサーバにアップロードする(アリクラウドのossを使っています。自分の状況に応じてrouter/uplload.jsのコードを修正できます。)
  • 顔写真補正
  • コメント:socket.io
  • リアルタイムメッセージ
  • 個人のホームページを見る
  • リアルタイムチャット:socket.io
  • トップページのプルダウンリフレッシュ:better-scroll
  • 検索:検索ユーザとダイナミック、local Strageを使用して履歴検索記録
  • を保存する。
    改善が必要である
  • 同じユーザの複数のデバイスが同時に登録されると、socket.ioに問題が発生しますので、ログインを制限しますか?データベース構造を変更しますか?
  • モバイル端末のピット:あるブラウザはカートンができて、Safariは入力ボックスに傍受できないで検索キー(心が崩壊したのです)を押します。
  • resize時better-scrollの小さいbug
  • は改ページ要求をしていません。全部のデータを一括で要求する
  • です。
  • コメント。の名前はそのままusenameを使いました。改名したら問題があります。。。暇があれば、
  • に変えています。
    インストール
    二つのファイルディレクトリの下にnpm installをインストールして、serverフォルダの下にnode ap.js、blogPhoneの下でnpm run devをインストールして、local hostを開けてください。8081でいいです。
    分析のまとめ
    sockete.io
    socket.ioを導入する
    サービス:
    
      let serve = app.listen(3001);
    
      const io = socketio(serve);
    
      io.on('connection', socket => {
    
        socket.on('login', (username) => {
    
                    console.log(username+'   !');
    
                });
    
      }
    
    クライアント:
    indexに導入する
    
    
        
    
          const socket = io.connect('http://47.107.66.252:3001');
    
        
    全体の考え
    必要なデータをvuexに保存し、ap.vueのudateBySocket()関数全体でサービス端末emitのイベントを傍受し、ルート情報によってデータが一般的に処理されるか、それともダイアログページに渡されるかを判断します。
    コアコード
    サービス端末(express実現)
            let serve = app.listen(3001);
            const io = socketio(serve);
            io.on('connection', socket => {
                const socketId = socket.id;
                //       username socketId    
                socket.on('login', (username) => {
                    socketHandler.saveUserSocketId(username, socketId)
                });
    
                socket.on('chat',(data) => {
                    Idtoid.findOne({
                        username: data.to_user
                    }).then((rs) => {
                    //               socketId
                        io.to(rs.socketid).emit('starChat',{
                            from_user:data.from_user,
                            message:data.message,
                            time:data.time,
                            avater:data.avater,
                            _id:data._id
                        })
                    })
                })
            })
    ap.vueupdate_chatList:チャットリストを更新するmutation
    ...mapMutations([
            'update_chatList'
          ]),
    updateBySocket() {
            socket.removeAllListeners();
            socket.on('receiveMsg', (data) => {
              let from_user = data.from_user;
              //        from_user    ,          
              if (this.$route.query.chatwith == from_user) {
                return;
              }
              this.update_chatList(data);
            })
          }
    ダイアログページchat.vuedataList:現在のダイアログのチャット記録
    //    
          sendMessage() {
            if (!this.userInfo._id){
              Toast("    !");
              return;
            }
            if (this.content == '') {
              return;
            }
            this.axios.post('/chat/chatwith', {//         
              chatWithId: this.tUserInfo._id,
              user_id: this.userInfo._id,
              content: this.content
            }).then((result) => {
              //           dataList 
              this.dataList.push({
                user_id: {//      ,        
                  avater: this.userInfo.avater
                },
                chatWith: {
                  _id: this.chatWithId
                },
                addTime: Date.now(),
                content: this.content
              });
              //         
              this.update_chatList({
                _id: this.tUserInfo._id,//   id
                from_user: this.chatWith,//       
                message: this.content,//    
                time: Date.now(),//  );
                me: true,//          
                avater:this.tUserInfo.avater
              });
              //         
              let data = {
                from_user: this.userInfo.username,//   
                to_user: this.chatWith,//   
                message: this.content,//    
                time: Date.now(), //  );
                avater: this.userInfo.avater,
                _id: this.userInfo._id
              };
              socket.emit('chat', data);
              this.content = '';
            })
          },
          updateBySocket() {
            socket.on('receiveMsg', (data) => {
              //             
              if (data.from_user == this.chatWith) {
                //              
                this.dataList.push({
                  chatWith: {
                    _id: this.userInfo._id
                  },
                  user_id: {//     
                    avater: data.avater
                  },
                  addTime: data.addTime,
                  content: data.message
                });
                this.update_chatList({
                  _id: this.tUserInfo._id,
                  from_user: this.chatWith,//       
                  message: data.message,//    
                  time: data.addTime,//  );
                  me: true,//           
                  avater:this.tUserInfo.avater
                });
              }
            })
          }
    vuex muttions.js
    [types.UPDATE_CHATLIST](state, data) {
        let flag = 0;//                 
        state.chatList.forEach((item)=>{
          if (item.chatWith.username == data.from_user) {
            flag = 1;
            if (!data.me) {//             
              item.unread++;
              state.unread++;
            }
            //  
            item.content = data.message;
            item.addTime = data.time;
            //       
            state.chatList.sort((a, b) => {
              return new Date(b.addTime) - new Date(a.addTime)
            });
            //    
            return false;
          }
        });
        //            
        if (!flag&&!data.me) {
          //      
          state.chatList.unshift({
            chatWith: {
              avater: data.avater,
              username: data.from_user,
              _id: data._id
            },
            addTime: data.time,
            content: data.message,
            unread: 1
          });
            state.unread++;
        }else if (!flag&&data.me){//          ,     unread
          state.chatList.unshift({
            chatWith: {
              avater: data.avater,
              username: data.from_user,
              _id: data._id
            },
            addTime: data.time,
            content: data.message,
          });
        }
      }
    締め括りをつける
    socket.ioの簡単な使い方は実は難しくないです。以下のいくつかの関数を身につけておけばいいです。socket.emit():接続を確立したクライアントにメッセージを送信する。socket.on():クライアント送信情報を傍受するio.to(socketid).emit():指定されたクライアントにメッセージを送信するsocket.broadcast.emit():接続を確立したクライアントを除いた全てのクライアントにブロードキャストする。io.sockets.emit():すべてのクライアントにブロードキャストする
    vue
    いくつかのプロジェクトの難しさをまとめます。
  • ajaxはライフサイクル関数createdで開始し、dom操作はライフサイクル関数mountedで動作し、dom要素が完全に掛かってから操作する場合はnextTickで動作する必要があります。例えば、
  • mounted() {
          this.$nextTick(() => {
            this.initImg();
          })
        }
  • により動的に生成されたdom要素は、mountedではrefでは取得できません。ライフサイクル関数udatedで
  • を取得する必要があります。
  • keepalive後のコンポーネントは、ジャンプが必要なときに動作する場合、ルーティング・ガードとライフサイクル関数activedとの組み合わせで使用できます。
    beforeRouteEnter(to, from, next) {
          if (from.path == '/upload' ) {
            next(vm => {
              vm._getList = true
            })
          } else {
            next()
          }
        }
    activated() {
          this.$nextTick(() => {
            if (this._getList) {
              this.getPyqLists();
            }
          })
        }
    画像のアップロードとプレビュー部分
    htmlの部分は主にweuiの形を借りました。