從 0 到 1 開發一個聊天通訊 服務 覆盤總結分享

{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"🌟文章首發InfoQ平臺🌟","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在上個月初,接到一個需求,要開發一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天通訊","attrs":{}}],"attrs":{}},{"type":"text","text":" 模塊 並且 集成到 項目中的多個 入口,實現業務數據的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"記錄追蹤","attrs":{}}],"attrs":{}},{"type":"text","text":".","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接到需求後,還挺開心,這是我第一次 搞 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"通訊","attrs":{}}],"attrs":{}},{"type":"text","text":" 類的需求,之前一直是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B 端","attrs":{}}],"attrs":{}},{"type":"text","text":" 的業務需求,不過現在也是在做這個方向,感覺 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 端 方向 挺有意思,管理着項目的整個項目上游和下游,然後服務於 內部人員 和 外部人員 使用,感覺挺自豪的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面就就跟着我來看看 如何 開發一個 聊天通訊 服務吧 ! (","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"主要站在前端的角度來講如何開發設計","attrs":{}},{"type":"text","text":" )","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"技術棧","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/90/90680f279de5480c9db4b921eb0c8265.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Vue 2.x","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Websoket","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Vuex","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Element","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"vue-at","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本項目是 以 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue","attrs":{}}],"attrs":{}},{"type":"text","text":" 技術棧生態開發的,其實不管用什麼","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"語言","attrs":{}}],"attrs":{}},{"type":"text","text":" , ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"思路是關鍵 !","attrs":{}}],"attrs":{}},{"type":"text","text":" 知道每一步需要幹什麼, 然後將每一步操作 整合起來 , 最終服務就跑起來了.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當中的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"每一步需要幹什麼","attrs":{}}],"attrs":{}},{"type":"text","text":" 就是 編程 中的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"function","attrs":{}}],"attrs":{}},{"type":"text","text":" 功能,根據這個功能然後在細化分析需要有到哪些","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"技術點","attrs":{}}],"attrs":{}},{"type":"text","text":" 。在開發的過程中,你不可能對整個鏈路的所有","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"技術點","attrs":{}}],"attrs":{}},{"type":"text","text":" 熟悉,這就需要遇到啥困難,臨時學習就可以了。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"開始分析需求","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先,我們要等待 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"UI","attrs":{}}],"attrs":{}},{"type":"text","text":" 設計師 的設計稿 畫出來, 然後根據 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"UI","attrs":{}}],"attrs":{}},{"type":"text","text":" 設計師的 設計稿分析整體 聊天通訊 的結構,從","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"view","attrs":{}}],"attrs":{}},{"type":"text","text":" 結構 來 劃分 應該 大體 包括哪些 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"component","attrs":{}}],"attrs":{}},{"type":"text","text":" , 每個","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"component","attrs":{}}],"attrs":{}},{"type":"text","text":" 中 又包括哪些小的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"component","attrs":{}}],"attrs":{}},{"type":"text","text":" , 這樣","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" 從 大 到 小","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方向將 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"設計稿","attrs":{}}],"attrs":{}},{"type":"text","text":" 轉化爲 程序員視角的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"component","attrs":{}}],"attrs":{}},{"type":"text","text":" .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"確立了有哪些","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"component","attrs":{}}],"attrs":{}},{"type":"text","text":" , 接下來 就是 確定 每個 小的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"component","attrs":{}}],"attrs":{}},{"type":"text","text":" 又有哪些 功能了。 現在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"UI","attrs":{}}],"attrs":{}},{"type":"text","text":" 設計師們,一般畫完界面後,會通過","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"第三方軟件 / 平臺 ","attrs":{}}],"attrs":{}},{"type":"text","text":" 來將效果圖 轉化成網頁,並且可以通過 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"URL","attrs":{}}],"attrs":{}},{"type":"text","text":" 可以直接訪問,當光標放到頁面中的某個元素時,可以獲取到當前元素的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"css style","attrs":{}}],"attrs":{}},{"type":"text","text":" , 不過,我建議不之 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"copy","attrs":{}}],"attrs":{}},{"type":"text","text":" ,有時和自己寫的佈局代碼會衝突,按需","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"copy","attrs":{}}],"attrs":{}},{"type":"text","text":" .","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"效果圖","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"真實效果圖,我就在這裏不放出來了,爲了保密性,只把整體結構,列出來,然後帶着大家分析結構和功能,如何進行編碼設計和組件設計。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/56/56b5f507223cf0c7ff3ca44cb1c030d0.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"功能分析圖","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f9/f95068020d428bda41758f3e7faa6221.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根據效果圖,在進行組件劃分時,我要記住這個原則:","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"高內聚,低耦合","attrs":{}}],"attrs":{}},{"type":"text","text":" , 組件職責單一性","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們將組件劃分爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"聯繫人組件","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"聊天組件","attrs":{}}],"attrs":{}},{"type":"text","text":" ---- 包括了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"歷史記錄組件","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"功能根據 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"UI","attrs":{}}],"attrs":{}},{"type":"text","text":" 設計師 提供的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"URL","attrs":{}}],"attrs":{}},{"type":"text","text":" 網頁來看交互效果來定,並和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"組長","attrs":{}}],"attrs":{}},{"type":"text","text":" / ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"產品經理","attrs":{}}],"attrs":{}},{"type":"text","text":" 交流需求,確定需求,以及砍掉不合理需求。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"需求確定後,就是梳理組件部分的功能了。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"組件構成","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在分析組件之前,我們需要先了解一下","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue Component","attrs":{}}],"attrs":{}},{"type":"text","text":" ,使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 朋友應該很熟悉了,一個組件的構成由以下組成:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"data","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件內部狀態","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"computed","attrs":{}}],"attrs":{}},{"type":"text","text":" 計算屬性,監聽","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"data","attrs":{}}],"attrs":{}},{"type":"text","text":" 變化來實現對應的業務邏輯需求","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"watch","attrs":{}}],"attrs":{}},{"type":"text","text":" 監聽","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"state","attrs":{}}],"attrs":{}},{"type":"text","text":" 變化","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"method","attrs":{}}],"attrs":{}},{"type":"text","text":" 組將的功能編寫區","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"props","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件接受","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"父組件","attrs":{}}],"attrs":{}},{"type":"text","text":" 傳遞來的值,進行約束類型等","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"lifecycle","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件的生命週期, 可以在組件創建到銷燬的過程中執行對應的業務邏輯","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/18/1899f5f21467a50565e6f3a8ef0239f0.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"聯繫人組件","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個組件主要是用來在聊天的時候,可以通過分組快速的找到某個人聯繫它,功能相對簡單。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"功能:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"查找聯繫人","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"有通知某人操作","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"功能分析","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"功能1: 查找聯繫人","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過現有聯繫人","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"json","attrs":{}}],"attrs":{}},{"type":"text","text":" 數據來 查找輸入的聯繫人進行匹配。 (簡單)","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"功能2: 通知某人","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當用戶點擊到某個聯繫人時,將點擊的人 放到輸入框裏 顯示 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"@xxx","attrs":{}}],"attrs":{}},{"type":"text","text":" [ 經過格式化處理 ] , 並將選中的聯繫人信息加入到發送消息的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"json","attrs":{}}],"attrs":{}},{"type":"text","text":" 對象中。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有多種實現方案,當用戶點擊了某聯繫人時,將觸發事件,攜帶值傳遞給","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"父組件[聊天組件的入口 index.vue ] 接收","attrs":{}}],"attrs":{}},{"type":"text","text":",然後將值傳遞給 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天主體組件","attrs":{}}],"attrs":{}},{"type":"text","text":" ,通過 在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天主體組件","attrs":{}}],"attrs":{}},{"type":"text","text":" 中 通過 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"$refs","attrs":{}}],"attrs":{}},{"type":"text","text":" 進行傳遞值。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面只提供示例代碼","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從聯繫人列表獲取選中聯繫人","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"//聯繫人組件 concat.vue\n\n\ngetLogname(val){\n this.$emit('toParent',{tag:'add',logname:val})\n},\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"聊天框顯示選中的聯繫人","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在聊天入口組件 接收 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"子向父","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件傳遞 選中聯繫人數據,然後給 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天主體","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件綁定 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ref","attrs":{}}],"attrs":{}},{"type":"text","text":" , 通過","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"refs","attrs":{}}],"attrs":{}},{"type":"text","text":" 來將聯繫人數據傳遞到 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天主體","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件顯示。 [這塊 數據傳遞有多種方法,例如 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vuex","attrs":{}}],"attrs":{}},{"type":"text","text":"]","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"//聊天組件入口 index.vue 它包括 聯繫人組件 聊天主體組件 歷史記錄組件\n\n//聯繫人組件\n\n\n//聊天主體組件 \n\n\n\n \n // 接受\n innerHtmlToChat(data){\n this.$refs.chatRoom.$refs.inputConents.innerHTML+=` @ ${data.logname}` //拼接到聊天輸入框裏\n}, \n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"效果展示","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e9/e935e894209ccdaddb7096ba954a02bb.gif","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"從聯繫人列表選中人員,發送消息","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6b/6bcfea54130d2c8da6545e0ba8c1d6fa.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"@人 接收到推送消息","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"聊天主體組件","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個組件就負責的功能就多了,這塊我主要把關鍵的功能帶大家來分析過一遍","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關鍵功能;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" 好友功能,實現推送通知(在線通知 / 離線-上線通知)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"聊天工具 [ ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"支持表情","attrs":{}}],"attrs":{}},{"type":"text","text":" ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"支持大文件上傳","attrs":{}}],"attrs":{}},{"type":"text","text":" ]","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"發送消息 [ ` 這塊就可以跟業務掛鉤了,發送信息時,並攜帶一些符合你項目需求的數據]","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"功能分析","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"功能1 : @ 實現","attrs":{}}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"vue-at","attrs":{}}],"attrs":{}},{"type":"text","text":" 文檔 : https://github.com/von7750/vue-at","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它的功能和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"微信","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"QQ ","attrs":{}}],"attrs":{}},{"type":"text","text":" **@ ** 功能一樣,在聊天輸入框裏,當你 輸入 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" 鍵時, 彈出好友列表,然後從中選擇聯繫人進行聊天。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"@ ","attrs":{}}],"attrs":{}},{"type":"text","text":" 功能必須包括以下3個關鍵功能;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以彈出聯繫人列表","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以監聽輸入字符內容進行過濾顯示對應數據","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"刪除 @ 聯繫人","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":".......","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一開始, 我是 自己造了個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" 功能 輪子 搞了搞,後來才發現市場上有相應的輪子,直接用第三方了,挺不錯的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"vue-at","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面來跟着我,來捋一下思路如何實現這個輪子,此處就不放實現代碼了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先來分析一波:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當在編輯區,輸入 @ 時, 彈出框","attrs":{}}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"mounted","attrs":{}}],"attrs":{}},{"type":"text","text":" 生命週期中監聽 按鍵 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"code","attrs":{}}],"attrs":{}},{"type":"text","text":" = 50 / 229 (中文/英文) 時,做出處理","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"由於我們這塊採用的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"div 可編輯屬性","attrs":{}}],"attrs":{}},{"type":"text","text":" ,那麼就獲取到 可編輯屬性的光標位置","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"然後通過光標位置 動態來改變 彈出框聯繫人列表的樣式 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"top","attrs":{}}],"attrs":{}},{"type":"text","text":" ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"left","attrs":{}}],"attrs":{}},{"type":"text","text":" , 實現跟着光標的 位置顯示聯繫人列表。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"然後 從列表中選擇 聯繫人進行聊天,並將 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聯繫人列表彈框","attrs":{}}],"attrs":{}},{"type":"text","text":" 隱藏掉。","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面就實現了基本的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"選中聯繫人功能","attrs":{}}],"attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"刪除選中的聯繫人","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於這塊是採用的可編輯屬性, 我們可以獲取選中的人,但","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"無法直接判斷是刪除的哪個人","attrs":{}},{"type":"text","text":",這時,只能通過判斷 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"innerHTML","attrs":{}}],"attrs":{}},{"type":"text","text":" 中是否包含某聯繫人,來進行刪除已保存的聯繫人。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這時,已經基本滿足了業務需求實現了。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三方插件已經的夠好了,我們就沒必要再造輪子,浪費時間了, 但 實現思路 必須的懂。 下面,我就來演示如何使用 第三方插件","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"vue-at","attrs":{}}],"attrs":{}},{"type":"text","text":" 實現 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" 功能","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1. 安裝插件","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"npm i [email protected]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2.組件 內部導入插件組件","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"import At from \"vue-at\";\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"3.註冊插件組件","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":" components: {\n At\n },\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"4. 頁面中使用","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"At","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件 必須包括 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"可編輯","attrs":{}}],"attrs":{}},{"type":"text","text":" 輸入內容區域, 這樣,當輸入 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,會彈出聯繫人列表框。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"members","attrs":{}}],"attrs":{}},{"type":"text","text":" : 數據源","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"filter-match","attrs":{}}],"attrs":{}},{"type":"text","text":" : 過濾數據","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"deleteMatch","attrs":{}}],"attrs":{}},{"type":"text","text":" : ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"刪除的聯繫人","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"insert","attrs":{}}],"attrs":{}},{"type":"text","text":" : 獲取聯繫人","attrs":{}}]}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\n \n
\n
\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"// 過濾聯繫人\nfilterMatch(name, chunk) {\n return name.toLowerCase().indexOf(chunk.toLowerCase()) === 0;\n},\n// 刪除聯繫人\ndeleteMatch(name, chunk, suffix) {\n this.contactList = this.contactList.filter(\n item => item.logname != chunk.trim()\n );\n return chunk === name + suffix;\n},\n// 獲取聯繫人\ngetValue(val) {\n this.contactList.push({ logname: val });\n},\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/43/437b3b7b29e6b3c0f8108efa81ab0535.gif","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"功能2:聊天工具箱","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"聊天軟件除了普通文字聊天,還有一些輔助服務來增加聊天的豐富性,例如: 表情 , 文件上傳, 截圖上傳 .... 功能","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們先來看看 市場 熱門聊天軟件它們有哪些 聊天工具。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"微信聊天工具箱","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"表情","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"文件上傳","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"截屏","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"聊天記錄","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"視頻聊天 / 語音聊天","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/34/34e651ee28ac70d29f3c1e1c119e7f85.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"微信聊天工具箱","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"QQ","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":" 聊天工具箱","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"表情","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"GIF 動圖 ","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"截屏","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"文件上傳","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"騰訊文檔","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"圖片發送","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"..... 騰訊業務相關功能","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/44/44cf5bacb16f11cf098ed4487595c864.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"QQ聊天工具箱","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"介紹了市場上熱門聊天的工具箱有哪些工具,迴歸正題: 我們的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天工具箱","attrs":{}}],"attrs":{}},{"type":"text","text":" 有哪些功能呢, 其實有哪些功能根據 業務來定,後期工具箱可以不斷擴充。 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"我們的工具箱基本上滿足日常聊天需求","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"表情","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"文件上傳","attrs":{}}],"attrs":{}},{"type":"text","text":" 支持大文件 ( 幾個G 都可以)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"截屏","attrs":{}}],"attrs":{}},{"type":"text","text":" ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Ctrl + Alt + A ","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"歷史記錄","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面我就來將比較幾個重要的功能: ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"文件上傳","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" 截屏","attrs":{}}],"attrs":{}},{"type":"text","text":" , 其它功能都很簡單。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"文件上傳","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上傳組件我採用的是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Element el-upload","attrs":{}}],"attrs":{}},{"type":"text","text":" 組件,由於我業務 要求上傳文件支持大文件, 採用的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"分片續傳","attrs":{}}],"attrs":{}},{"type":"text","text":" 方式來實現。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"分片續傳思路","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"我們上傳也是採用的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"websoket","attrs":{}}],"attrs":{}},{"type":"text","text":" 上傳,首次發送時,必鬚髮送一些必要的文件基本信息","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":"none"},"content":[{"type":"blockquote","content":[{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"文件名","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"文件大小","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"發送者","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"一些跟業務相關的字段數據","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"時間","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"文件分片大小","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"文件分片片數","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":9,"align":null,"origin":null},"content":[{"type":"text","text":"上傳進度標識","attrs":{}}]}]}],"attrs":{}}],"attrs":{}}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":10,"align":null,"origin":null},"content":[{"type":"text","text":"首次發送完文件的基本信息後,開始發送分片文件信息,首先將文件分片後,然後依次讀取片文件流,發送時攜帶文件流,等文件分片循環結束後,發送一個結束標識告訴後臺發送完畢了 [","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"這塊你可以和後端商量設計數據格式","attrs":{}}],"attrs":{}},{"type":"text","text":"]","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"示例代碼演示","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\n \n
\n 將文件拖到此處然後點擊上傳文件\n
\n
\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"覆蓋掉 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Element","attrs":{}}],"attrs":{}},{"type":"text","text":" 默認上傳方式,改用自定義上傳方式。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"開始分片上傳","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":" // 上傳文件\n httpRequest(options) {\n let that = this;\n\n //每個文件切片大小\n const bytesPerPiece = 1024 * 2048;\n // 文件必要的信息\n const { name, size } = options.file;\n // 文件分割片數\n const chunkCount = Math.ceil(size / bytesPerPiece);\n \n // 獲取到文件後,發送文件的基本信息\n const fileBaseInfo = {\n fileName: name,\n fileSize: size,\n segments: \"historymessage\",\n loginName: localStorage.getItem(\"usrname\"),\n time: new Date().toLocaleString(),\n chunkSize: bytesPerPiece,\n chunkCount: chunkCount,\n messagetype: \"bufferfile\",\n process: \"begin\",\n \n \n ... 一些跟業務掛鉤的 字段\n\n };\n\n\n that.$websoketGlobal.ws.send(JSON.stringify(fileBaseInfo));\n \n let start = 0;\n\n // 進行分片\n var blob = options.file.slice(start, start + bytesPerPiece);\n //創建`FileReader`\n var reader = new FileReader();\n //開始讀取指定的 Blob中的內容, 一旦完成, result 屬性中保存的將是被讀取文件的 ArrayBuffer 數據對象.\n reader.readAsArrayBuffer(blob);\n //讀取操作完成時自動觸發。\n reader.onload = function(e) {\n // 發送文件流\n that.$websoketGlobal.ws.send(reader.result);\n start += bytesPerPiece;\n if (start < size) {\n var blob = options.file.slice(start, start + bytesPerPiece);\n reader.readAsArrayBuffer(blob);\n } else {\n fileBaseInfo.process = \"end\";\n // 發送上傳文件結束 標識\n that.$websoketGlobal.ws.send(JSON.stringify(fileBaseInfo));\n }\n that.uploadStatus = false;\n that.fileList = [];\n };\n },\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"效果演示","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/04/0433ba3974595db3236eab549b76b4f8.gif","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3d/3da0466f0f1165a3a144e48897e8a26d.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"功能3: 截屏功能","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"PC","attrs":{}}],"attrs":{}},{"type":"text","text":" 中,這是一個很重要的業務,通過這種技術可以從網上截取下自己感興趣的文章圖片供自己使用觀看,可以幫助人們更好的去理解使用知識。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於我們的輸入內容區域採用的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"可編輯","attrs":{}}],"attrs":{}},{"type":"text","text":" 區域,此處可以插入任意內容,也可以使用外部 的截圖功能,粘貼到輸入框區域,這塊就沒必要的","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"造輪子了","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1. 可編輯區域","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們給 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"div","attrs":{}}],"attrs":{}},{"type":"text","text":" 加上 該屬性 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"contenteditable","attrs":{}}],"attrs":{}},{"type":"text","text":" 就可以控制 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"div","attrs":{}}],"attrs":{}},{"type":"text","text":" 中可輸入哪些內容,外部複製過來內容也可以直接顯示,還可以顯示其帶的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"css","attrs":{}}],"attrs":{}},{"type":"text","text":" 效果。我們先來看看 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"contenteditable","attrs":{}}],"attrs":{}},{"type":"text","text":" 有哪些屬性吧 !","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/91/9120f72b1c1c887f4cdc40a2fee052fe.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"embedcomp","attrs":{"type":"table","data":{"content":"
描述
inherit默認值繼承自父元素
true或空字符串,表示元素是可編輯的;
false表示元素不是可編輯的。
plaintext-only純文本
caret符號
events
"}}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"注意","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不允許簡寫爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正確的用法是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"瀏覽器支持情況","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/59/59a8faacc53dd80aa69aff3c88f1236d.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d5/d53c319e01a3f271edda8d67c675713d.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"使用","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"
\n
\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"效果展示","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c1/c1c52548213645a2c5340be71522687e.gif","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2. 截屏","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於採用的是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"可編輯","attrs":{}}],"attrs":{}},{"type":"text","text":" ,那麼就可以隨意從外部 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"copy","attrs":{}}],"attrs":{}},{"type":"text","text":" , 哈哈,有意思的來了,支持 Windows 自帶的截屏 + PC 第三方 截屏......","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"💥快捷操作方法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"windows","attrs":{}}],"attrs":{}},{"type":"text","text":" 自帶的的截屏快捷鍵","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":"none"},"content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"截取整個屏幕 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Print Screen","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"截取當前活動屏幕 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" Alt+Print Screen","attrs":{}}],"attrs":{}}]}],"attrs":{}}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"QQ","attrs":{}}],"attrs":{}},{"type":"text","text":" 截屏功能,支持個性化操作截圖 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Ctrl + Alt + A ","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"微信","attrs":{}}],"attrs":{}},{"type":"text","text":" 截屏功能, 支持個性化操作截圖 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Alt + A","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"專門的截屏工具....","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"站在巨人的肩膀上, 直接起飛。😄 , 不過確實站在用戶角度想,這點確實有點不好😘。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"實際效果演示 ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2.1 微信截屏 show time","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bf/bf14908356f465fa998a76ce3f23bf01.gif","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2.2 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"QQ","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":" 截屏 ","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/99/99e52cbc8b0d72eb56b87bc95d634be8.gif","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"功能4: 發送功能","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個功能貫穿這個聊天項目,項目採用的是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"websoket","attrs":{}}],"attrs":{}},{"type":"text","text":" 實現的通信服務,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"全雙工通信","attrs":{}}],"attrs":{}},{"type":"text","text":" , 發送聊天內容時,需要攜帶一些很業務相關的數據,來實現業務跟蹤分析。下面,來簡單複習過一下 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"websoket","attrs":{}}],"attrs":{}},{"type":"text","text":" , 對沒有使用過","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"websoket","attrs":{}}],"attrs":{}},{"type":"text","text":" 同學也時學習。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/de/deb4781be795dcc2e65ea5fdd79014ef.jpeg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"WebSoket","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"WebSocket","attrs":{}}],"attrs":{}},{"type":"text","text":"是一種在單個TCP連接上進行全雙工通信的協議。 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WebSocket","attrs":{}}],"attrs":{}},{"type":"text","text":"使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"在WebSocket API","attrs":{}}],"attrs":{}},{"type":"text","text":"中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"WebSoket","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":" 特點","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"屬於服務器推送技術的一種。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"與 HTTP 協議有着良好的兼容性。默認端口也是80和443,並且握手階段採用 HTTP 協議.","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據格式比較輕量,性能開銷小,通信高效。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以發送文本,也可以發送二進制數據。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"沒有同源限制,客戶端可以與任意服務器通信。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"協議標識符是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ws","attrs":{}}],"attrs":{}},{"type":"text","text":"(如果加密,則爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"wss","attrs":{}}],"attrs":{}},{"type":"text","text":"),服務器網址就是 URL。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"WebSoket","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":" 操作 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"API","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"創建Websoket連接🔗","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let socket = new WebSocket(\"ws://域名/服務路徑\")\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"連接 Websoket 成功觸發","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"open()","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法在連接成功時,觸發","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"socket.onopen = function() {\n console.log(\"websocket連接成功\");\n};\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"發送消息","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":" send()","attrs":{}}],"attrs":{}},{"type":"text","text":"方法並傳入一個","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"字符串","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ArrayBuffer","attrs":{}}],"attrs":{}},{"type":"text","text":" 或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Blob","attrs":{}}],"attrs":{}},{"type":"text","text":" .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"socket.send(\"公衆號: 前端自學社區\")\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"接收服務端返回的數據","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"message","attrs":{}}],"attrs":{}},{"type":"text","text":" 事件會在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WebSocket","attrs":{}}],"attrs":{}},{"type":"text","text":" 接收到新消息時被觸發。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"socket.onmessage = function(res) { \n console.log(res.data)\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"關閉 WebSoket 連接 ","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"WebSocket.close()","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法關閉 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WebSocke","attrs":{}}],"attrs":{}},{"type":"text","text":"連接或連接嘗試(如果有的話)。 如果連接已經關閉,則此方法不執行任何操作。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"socket.onclose = function() {\n // 關閉 websocket\n console.log(\"連接已關閉...\");\n //斷線重新連接\n setTimeout(() => {\n that.initWebsoket();\n }, 2000);\n};\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"WebSoket 錯誤處理","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"websocket","attrs":{}}],"attrs":{}},{"type":"text","text":"的連接由於一些錯誤事件的發生 (例如無法發送一些數據)而被關閉時,一個","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"error","attrs":{}}],"attrs":{}},{"type":"text","text":"事件將被引發.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"// 監聽可能發生的錯誤\nsocket.addEventListener('error', function (event) {\n console.log('WebSocket error: ', event);\n});\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過上面我們瞭解了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Websoket","attrs":{}}],"attrs":{}},{"type":"text","text":" 如何使用,接下來就是 實操了,下面走起!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"項目採用的是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue","attrs":{}}],"attrs":{}},{"type":"text","text":" 技術棧,更多寫法偏向於 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue","attrs":{}}],"attrs":{}},{"type":"text","text":" 。 由於 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WebSoket","attrs":{}}],"attrs":{}},{"type":"text","text":" 貫穿整個項目,而且需要實時推送 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" , 我們將 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Websoket","attrs":{}}],"attrs":{}},{"type":"text","text":" 儘量放在全局入口,接收信息","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"onmessage","attrs":{}}],"attrs":{}},{"type":"text","text":" 事件也放在 入口文件中,這樣全局都能接收到數據,接收到的數據 利用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vuex","attrs":{}}],"attrs":{}},{"type":"text","text":" 進行管理聊天的數據 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"[ 歷史數據 推送數據 發送數據 ]","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1. 新建 一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"websoket ","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"文件,用於全局使用","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"export default {\n ws: {},\n setWs: function(wsUrl) {\n this.ws = wsUrl\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2. 在","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Vue ","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"入口文件","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"index.js","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"中 全局註冊","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"import Vue from 'vue'\nimport websoketGlobal from './utils/websoket'\n\n\nVue.prototype.$websoketGlobal = websoketGlobal\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"3. 在 App.vue 中 接收 Websoket 推送的消息","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這塊的設計很關鍵,決定了聊天數據的存儲和設計,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"過多細節代碼就不放了","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大體思路我說說一下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"傳輸格式上定了,那麼接收的數據結構也就定了,更多的就是在數據結構上下文章了, 前後端需要約束好字段屬性。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":"none"},"content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從聊天頁面顯示狀態來看:","attrs":{}}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"區分數據類型的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"字段","attrs":{}}],"attrs":{}},{"type":"text","text":",這樣前端在接收到推送的消息時,知道在頁面中該如何顯示,例如(該顯示圖片樣式還是文本樣式)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"區分發送消息顯示左右的字段, 前端通過接收到推送的消息時, 會首先判斷是否爲自己,不是的話顯示在左邊樣式","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"區分 系統的推送字段, 根據這個字段顯示對應的樣式。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"........... 更多字段屬性 需要根據你實際業務而來定","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"是","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"是","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從信息推送狀態來看:","attrs":{}}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" 推送全局 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Notification","attrs":{}}],"attrs":{}},{"type":"text","text":" 通知 和 聊天內部推送 設計","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"@","attrs":{}}],"attrs":{}},{"type":"text","text":" 推送 根據指定字段類型判斷 ,然後實現全局 推送","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"聊天內容推送","attrs":{}}],"attrs":{}},{"type":"text","text":": 由於它和具體某個聊天有關係,它也屬於歷史聊天數據,在聊天中根據 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"內容數據類型","attrs":{}}],"attrs":{}},{"type":"text","text":" 來確定如何顯示","attrs":{}}]}]}]}],"attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"mounted(){\n this.$websoketGlobal.ws.onmessage = res => {\n const result = JSON.parse(res.data);\n\n // 推送數據\n\n //聊天曆史數據 新增加發送的數據\n\n\n // 獲取聊天曆史數據\n\n //聊天曆史數據 新增加發送的數據\n\n };\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"4. 在聊天組件中使用 Websoket","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在聊天組件中,其實使用的就是 發送功能 和 獲取 歷史記錄 功能,還有就是根據 推送的消息內容字段來決定頁面中數據如何顯示。下面聊天的樣式代碼就不放了,主要放一下 發送消息的 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"示例代碼","attrs":{}},{"type":"text","text":" 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"send() {\n let that = this;\n\n // 定義數據結構: 傳遞什麼內容是 前提 前端和後端商量好的 \n const obj = {\n messageId: Number(\n Math.random()\n .toString()\n .substr(3, length) + Date.now()\n ).toString(36),\n //文件類型 \n messagetype: \"textmessage\",\n //@ 聯繫熱\n call: that.contactList,\n //聊天輸入內容 \n inputConent: that.$refs.inputConents.innerHTML ,\n // 當前時間 \n time: currentDate,\n\n ..... 再定義一些符合你業務的字段 \n };\n \n // 發送消息\n that.$websoketGlobal.ws.send(JSON.stringify(obj));\n that.$refs.inputConents.innerHTML = \"\";\n that.contactList = []\n}\n},\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在每次進入聊天組件時,需要首先獲取聊天的歷史記錄,聊天入口根據你的業務來定,傳遞必須參數.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"mounted(){\n this.$websoketGlobal.ws.send(\n JSON.stringify({\n id: 1\n messagetype: \"historymessage\"\n })\n );\n}\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"功能5: 離線 / 在線推送","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個相當於 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"微信","attrs":{}}],"attrs":{}},{"type":"text","text":" / ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"QQ","attrs":{}}],"attrs":{}},{"type":"text","text":" 在線 和 上線 收到的消息。 當 A 用戶 @ 了 B 用戶 (","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"此時 B 用戶 不在線","attrs":{}}],"attrs":{}},{"type":"text","text":"),當 B 用戶 上線時,它會收到 一條信息。","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"這個是怎麼實現呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我就結合項目來大體說一下思路,具體實現就不說了,實現主要在後端。 當時,向後端大佬還特意請教了一下。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當 A用戶 登錄了 系統,此時就會和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Websoket","attrs":{}}],"attrs":{}},{"type":"text","text":" 建立連接,後端會記錄起來,該用戶的標識,狀態爲登錄。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當 A 用戶 @ 了 B 用戶 ,正常邏輯會推送給B用戶一條信息,B 不在線,就不推給他?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"怎麼知道B 用戶是否在線呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前面也說到了,登錄系統就會建立連接,後端會暫時存儲起來在線的用戶,當A 用戶 向 B 用戶發送的消息後,後端看","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"在線用戶列表","attrs":{}}],"attrs":{}},{"type":"text","text":"裏沒有B 用戶,那麼他就不會推送。當B用戶上線了,會自動推送,前端接收,直接提醒用戶。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/54/543048aa36c8d48da9661eb301ff123f.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"聊天室入口組件","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"聊天室入口組件包括: ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聯繫人組件 ","attrs":{}}],"attrs":{}},{"type":"text","text":" + ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" 聊天主體組件","attrs":{}}],"attrs":{}},{"type":"text","text":" , 它做的事情其實很簡單了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"如何打開聊天室 ?","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"如何給聊天室傳遞歷史數據?","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule","attrs":{}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"如何打開聊天室?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"外部可能通過多個入口來打開聊天室,通過一個狀態來控制顯示聊天室,傳遞類型爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Boolean","attrs":{}}],"attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"如何給聊天室傳遞歷史數據?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"外部通過給聊天室組件傳遞必要數據,這些必要數據然後在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聯繫人組件","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" 聊天主體組件","attrs":{}}],"attrs":{}},{"type":"text","text":" 內部消耗,獲取各自需要的數據,這樣聊天室入口組件的職責單一,很好進行管理。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面來看看聊天室的入口組件:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"內部的通信主要是由 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vuex","attrs":{}}],"attrs":{}},{"type":"text","text":" 來進行管理, 由於聊天室在全局都需要喚醒,可以將","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天入口組件","attrs":{}}],"attrs":{}},{"type":"text","text":"放到全局入口文件,這樣,不管項目需要多少個入口,只需要傳遞喚醒","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天入口組件的狀態","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"入口組件需要的必要參數","attrs":{}}],"attrs":{}},{"type":"text","text":" 來獲取歷史聊天數據。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣,當項目其它模塊需要 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天室","attrs":{}}],"attrs":{}},{"type":"text","text":" 這個功能,只需要 **一行代碼 ** 即可 接入,作爲插槽接入。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"html"},"content":[{"type":"text","text":"\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"openChat(row){\n this.$store.commit(\"Chat\", { status: true, data: row });\n},\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在開發這個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天服務","attrs":{}}],"attrs":{}},{"type":"text","text":" 中也遇到了很多難點和坑,不過一個一個踩過來了,越往後做思路越開。 開發完這個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"聊天服務","attrs":{}}],"attrs":{}},{"type":"text","text":" 對技術理解又有更深的認知了,在你感覺某個功能很難困難,不知道怎麼實現,你先行動起來,按照自己的思路一步一步推理,推理的過程就會思路打開了,會有多種方式來實現了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"最後","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"聊天服務開發了一個月,寫文章寫了一個周左右,寫作不易,如果文章學到了,點個贊👍👍👍關注,支持一下!","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章