摘要:如果末尾不為文本,也添加一個(gè)空的文本對(duì)象。如果為空,那么末尾項(xiàng)就是唯一的文本項(xiàng)
在寫聊天系統(tǒng)的時(shí)候,不可避免地要對(duì)聊天系統(tǒng)中的消息做一些解析
常見(jiàn)的比如一句話中帶有emoji、link等信息的時(shí)候,要把emoji解析成圖片、把link轉(zhuǎn)成可以點(diǎn)擊的
(項(xiàng)目中沒(méi)有做對(duì)圖片做行內(nèi)處理,而是把圖片像微信一樣作為多帶帶消息發(fā)送)
我們知道react的標(biāo)簽都是jsx的,所以在解析消息的時(shí)候,就必須在得到消息內(nèi)容的時(shí)候,就先把消息內(nèi)容分段截取
比如這樣一則消息
今天吃飯了嗎?[emoji]我還沒(méi)吃呢[emoji],給你個(gè)鏈接看看吧!http://www.google.com/
emoji要解析成圖片,http://www.google.com/ 要解析成可以點(diǎn)擊的鏈接,之間的文字要解析成文本
jquery時(shí)代,只需要使用正則匹配emoji,替換成圖片,用正則匹配鏈接,替換成a標(biāo)簽即可
但是在react里,這三者對(duì)應(yīng)的是不同的jsx標(biāo)簽。所以必須把文本解析成分段式的
思路:
上面這句話,可以解析成6部分
part1: 今天吃飯了嗎? part2: [emoji] part3: 我還沒(méi)吃呢 part4: [emoji] part5: ,給你個(gè)鏈接看看吧! part6: http://www.google.com/
每部分對(duì)應(yīng)使用不同的jsx標(biāo)簽
第一步,我們先使用正則匹配emoji和鏈接
分別的正則如下
(匹配鏈接應(yīng)該有更優(yōu)秀的正則)
var emojiregex = new RegExp(/ud83c[udf00-udfff]|ud83d[udc00-ude4f]|ud83d[ude80-udeff]/g, "g"); // 匹配emoji字符 var matchUrlRegex = new RegExp(/(https?:)//([^/]+)(/[^?]*)?(?[^#]*)?(#.*)?/g,"g"); // 匹配url的正則 var emojiRegArray = text.match(emojiregex); // 匹配了所有的emoji的詞 var urlRegArray = text.match(matchUrlRegex);
得到兩個(gè)數(shù)組,分別是匹配到的emoji和匹配到的url
第二步,使用index()方法,獲取每個(gè)emoji、url的位置、長(zhǎng)度,并記錄
var indexEmojiArray = []; // 記錄表情的位置、內(nèi)容的數(shù)組 var indexUrlArray = []; // 記錄鏈接的位置、內(nèi)容的數(shù)組 var pos1 = -1, pos2 = -1;//頭 if(emojiRegArray){ for (let i = 0; i < emojiRegArray.length; i++) { pos1 = text.indexOf(emojiRegArray[i], pos1 + 1); indexEmojiArray.push({ type: 1, // type為1表示是表情 pos: pos1, length: emojiRegArray[i].length, res: emojiRegArray[i], }); } } if(urlRegArray){ for (let i = 0; i < urlRegArray.length; i++) { pos2 = text.indexOf(urlRegArray[i], pos2 + 1); indexUrlArray.push({ type: 3, // type為1表示是url pos: pos2, length: urlRegArray[i].length, res: urlRegArray[i], }); } }
第三步,按照這些元素在消息中的位置,兩個(gè)數(shù)組合并成一個(gè)數(shù)組
// 合并兩個(gè)數(shù)組 var indexArray = []; // 以上兩個(gè)數(shù)組按照pos順序合并的數(shù)組 if(emojiRegArray && urlRegArray){ let point1 = 0,point2 = 0; while(point1 < indexEmojiArray.length || point2 < indexUrlArray.length){ if(!indexEmojiArray[point1]){ // emoji加完了 indexArray.push(indexUrlArray[point2]); point2++; }else if(!indexUrlArray[point2]){// url加完了 indexArray.push(indexEmojiArray[point1]); point1++; }else{ // 兩個(gè)都沒(méi)加完 if(indexEmojiArray[point1].pos < indexUrlArray[point2].pos){ indexArray.push(indexEmojiArray[point1]); point1++; }else{ indexArray.push(indexUrlArray[point2]); point2++; } } } }else if(emojiRegArray && !urlRegArray){ // 有emoji沒(méi)有url indexArray = indexEmojiArray; }else if(!emojiRegArray && urlRegArray){ // 有url沒(méi)有emoji indexArray = indexUrlArray; }
第四步
現(xiàn)在,我們得到了一個(gè)indexArray,存儲(chǔ)了emoji和url的位置和長(zhǎng)度的數(shù)組
現(xiàn)在我們要把文本也加進(jìn)去,并且,emoji替換成圖片
// 這里開始把indexArray加工成contentArray let contentArray = []; let point = 0; // 記錄當(dāng)前指針位置 for (let i = 0; i < indexArray.length; i++) { // 把這一項(xiàng)和上一項(xiàng)之間的內(nèi)容push成文本 console.log(point); let textContent = text.substr(point, indexArray[i].pos-point); console.log(textContent); contentArray.push({type: 0, content: textContent}); // point += textContent.length; if(indexArray[i].type === 1){ // 如果這一項(xiàng)是emoji // contentArray.push({ type: 1, "resources": EMOJI_MAP[indexArray[i].res] || [] }); contentArray.push({ type: 1, resources: indexArray[i].res || [] }); point = indexArray[i].pos + indexArray[i].length; }else if(indexArray[i].type === 3){ // 如果這一項(xiàng)是url contentArray.push({ type: 3, url: indexArray[i].res}); point = indexArray[i].pos + indexArray[i].length; } } // 加入末尾項(xiàng)。如果indexArray為空,那么末尾項(xiàng)就是唯一的文本項(xiàng) let lastPrevItemIndex = (indexArray[indexArray.length-1] ? indexArray[indexArray.length-1].pos+indexArray[indexArray.length-1].length : 0); contentArray.push({type: 0, content: text.substr(lastPrevItemIndex, text.length)});
最后得到的contentArray我們r(jià)eturn出去。
比較難的部分在第四步,思路是,我們使用一個(gè)指針,對(duì)消息做解析,一開始指針的位置為0
開頭不管如何都push一個(gè)文本對(duì)象進(jìn)入contentArray中
直到遇到emoji或者url位置為止
比如遇到的是emoji,我們把emoji解析成對(duì)象push到contentArray中,然后指針加上emoji的長(zhǎng)度
最后加上末尾。如果末尾不為文本,也添加一個(gè)空的文本對(duì)象。
完畢。
下面附上所有代碼
let stringToContentArray = function (text) { var emojiregex = new RegExp(/ud83c[udf00-udfff]|ud83d[udc00-ude4f]|ud83d[ude80-udeff]/g, "g"); var matchUrlRegex = new RegExp(/(https?:)//([^/]+)(/[^?]*)?(?[^#]*)?(#.*)?/g,"g"); // 匹配url的正則 var contentArray = []; if (!text) { // 沒(méi)有內(nèi)容 contentArray.push({ type: 0, "content": "[無(wú)內(nèi)容消息]" }); return contentArray; } var emojiRegArray = text.match(emojiregex); // 匹配了所有的emoji的詞 var urlRegArray = text.match(matchUrlRegex); // console.log(text); console.log("emojiRegArray:",emojiRegArray); console.log("urlRegArray:",urlRegArray); if (emojiRegArray === null && urlRegArray === null) { // 沒(méi)有emoji表情, 也沒(méi)有鏈接 contentArray.push({ type: 0, "content": text }); return contentArray; } var indexEmojiArray = []; // 記錄表情的位置、內(nèi)容的數(shù)組 var indexUrlArray = []; // 記錄鏈接的位置、內(nèi)容的數(shù)組 var indexArray = []; // 以上兩個(gè)數(shù)組按照pos順序合并的數(shù)組 var pos1 = -1, pos2 = -1;//頭 if(emojiRegArray){ for (let i = 0; i < emojiRegArray.length; i++) { pos1 = text.indexOf(emojiRegArray[i], pos1 + 1); indexEmojiArray.push({ type: 1, // type為1表示是表情 pos: pos1, length: emojiRegArray[i].length, res: emojiRegArray[i], }); } } if(urlRegArray){ for (let i = 0; i < urlRegArray.length; i++) { pos2 = text.indexOf(urlRegArray[i], pos2 + 1); indexUrlArray.push({ type: 3, // type為1表示是url pos: pos2, length: urlRegArray[i].length, res: urlRegArray[i], }); } } if(emojiRegArray && urlRegArray){ let point1 = 0,point2 = 0; while(point1 < indexEmojiArray.length || point2 < indexUrlArray.length){ if(!indexEmojiArray[point1]){ // emoji加完了 indexArray.push(indexUrlArray[point2]); point2++; }else if(!indexUrlArray[point2]){// url加完了 indexArray.push(indexEmojiArray[point1]); point1++; }else{ // 兩個(gè)都沒(méi)加完 if(indexEmojiArray[point1].pos < indexUrlArray[point2].pos){ indexArray.push(indexEmojiArray[point1]); point1++; }else{ indexArray.push(indexUrlArray[point2]); point2++; } } } }else if(emojiRegArray && !urlRegArray){ // 有emoji沒(méi)有url indexArray = indexEmojiArray; }else if(!emojiRegArray && urlRegArray){ // 有url沒(méi)有emoji indexArray = indexUrlArray; } console.log("indexArray: ", indexArray); // 這里開始把indexArray加工成contentArray let point = 0; // 記錄當(dāng)前指針位置 for (let i = 0; i < indexArray.length; i++) { // 把這一項(xiàng)和上一項(xiàng)之間的內(nèi)容push成文本 console.log(point); let textContent = text.substr(point, indexArray[i].pos-point); console.log(textContent); contentArray.push({type: 0, content: textContent}); // point += textContent.length; if(indexArray[i].type === 1){ // 如果這一項(xiàng)是emoji // contentArray.push({ type: 1, "resources": EMOJI_MAP[indexArray[i].res] || [] }); contentArray.push({ type: 1, resources: indexArray[i].res || [] }); point = indexArray[i].pos + indexArray[i].length; }else if(indexArray[i].type === 3){ // 如果這一項(xiàng)是url contentArray.push({ type: 3, url: indexArray[i].res}); point = indexArray[i].pos + indexArray[i].length; } } // 加入末尾項(xiàng)。如果indexArray為空,那么末尾項(xiàng)就是唯一的文本項(xiàng) let lastPrevItemIndex = (indexArray[indexArray.length-1] ? indexArray[indexArray.length-1].pos+indexArray[indexArray.length-1].length : 0); contentArray.push({type: 0, content: text.substr(lastPrevItemIndex, text.length)}); return contentArray; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/101491.html
摘要:傳統(tǒng)的網(wǎng)頁(yè)編程采用的三劍客來(lái)實(shí)現(xiàn),在微信小程序中同樣有三劍客。觀察者模式不難實(shí)現(xiàn),重點(diǎn)是如何在微信小程序中搭配其特有的生命周期來(lái)使用。交互事件傳統(tǒng)的事件傳遞類型有冒泡型與捕獲型,微信小程序中自然也有。 本文由作者鄒永勝授權(quán)網(wǎng)易云社區(qū)發(fā)布。 簡(jiǎn)介為了更好的展示我們即時(shí)通訊SDK強(qiáng)悍的能力,網(wǎng)易云信IM SDK微信小程序DEMO的開發(fā)就提上了日程。用產(chǎn)品的話說(shuō)就是: 云信 IM 小程序 S...
摘要:但是需要注意的一點(diǎn)是協(xié)議是建立在協(xié)議基礎(chǔ)之上的,需要經(jīng)過(guò)一次握手。所以連接的發(fā)起方仍是客戶端。是一個(gè)簡(jiǎn)潔而靈活的應(yīng)用框架提供一系列強(qiáng)大特性幫助你創(chuàng)建各種應(yīng)用。這也是為什么要采用協(xié)議來(lái)實(shí)現(xiàn)聊天室的原因。 從開始寫到完善差不多斷斷續(xù)續(xù)差不多半個(gè)月時(shí)間,雖然還沒(méi)有打到想要的效果但還是階段性總結(jié)一下。(下一步加入打算視頻通訊功能)本文默認(rèn)你已掌握 node 相關(guān)基礎(chǔ)知識(shí) GitHub地址:ht...
摘要:由于我們的富文本輸入框比較簡(jiǎn)單,所以只需要處理兩類數(shù)據(jù)即可,其一是普通的文本類型數(shù)據(jù),包括表情其二則是圖片類型數(shù)據(jù)。 最近折騰 Websocket,打算開發(fā)一個(gè)聊天室應(yīng)用練練手。在應(yīng)用開發(fā)的過(guò)程中發(fā)現(xiàn)可以插入 emoji ,粘貼圖片的富文本輸入框其實(shí)蘊(yùn)含著許多有趣的知識(shí),于是便打算記錄下來(lái)和大家分享。 倉(cāng)庫(kù)地址:chat-input-box預(yù)覽地址:https://codepen.io...
閱讀 2930·2021-11-22 15:22
閱讀 20180·2021-09-22 15:00
閱讀 1534·2021-09-07 09:58
閱讀 1300·2019-08-30 13:01
閱讀 2512·2019-08-29 16:27
閱讀 2404·2019-08-26 13:25
閱讀 1685·2019-08-26 12:13
閱讀 1013·2019-08-26 11:53