項(xiàng)目中要求實(shí)現(xiàn)一個(gè)功能箭券,在輸入框中輸入特定的搜索語(yǔ)句,當(dāng)輸入為關(guān)鍵字時(shí)圈浇,關(guān)鍵字高亮,且輸入滿一行進(jìn)行換行操作
首先分析如果想實(shí)現(xiàn)一部分關(guān)鍵字高亮靴寂,輸入框本身肯定是做不到的磷蜀,因?yàn)閷?shí)現(xiàn)高亮需要通過(guò)動(dòng)態(tài)的給關(guān)鍵字添加span標(biāo)簽,再給span標(biāo)簽中的內(nèi)容設(shè)置顏色
如果使用div,那必須給div添加contenteditable = "true"屬性百炬,使其div可輸入褐隆,其次監(jiān)聽按鍵是否抬起,對(duì)div中的內(nèi)容進(jìn)行檢測(cè)并替換關(guān)鍵字剖踊,我在嘗試這種方法時(shí)遇到了幾個(gè)問(wèn)題庶弃,第一個(gè)問(wèn)題是每次輸入內(nèi)容進(jìn)行替換后光標(biāo)自動(dòng)定位在開頭衫贬,此問(wèn)題在網(wǎng)上查找資料解決如下
function po_Last_Div(obj) {
? ? if (window.getSelection) {//ie11 10 9 ff safari
? ? ? ? obj.focus(); //解決ff不獲取焦點(diǎn)無(wú)法定位問(wèn)題
? ? ? ? var range = window.getSelection();//創(chuàng)建range
? ? ? ? range.selectAllChildren(obj);//range 選擇obj下所有子內(nèi)容
? ? ? ? range.collapseToEnd();//光標(biāo)移至最后
? ? }
else if (document.selection) {//ie10 9 8 7 6 5
? ? ? ? var range = document.selection.createRange();//創(chuàng)建選擇對(duì)象
? ? ? ? //var range = document.body.createTextRange();
? ? ? ? range.moveToElementText(obj);//range定位到obj
? ? ? ? range.collapse(false);//光標(biāo)移至最后
? ? ? ? range.select();
? ? }
}
第二個(gè)問(wèn)題為如果用戶將關(guān)鍵字改變,但程序進(jìn)行監(jiān)聽時(shí)獲取的還是加了span標(biāo)簽的內(nèi)容歇攻,所以當(dāng)關(guān)鍵字被修改成不是關(guān)鍵字時(shí)固惯,其高亮并沒(méi)有消失,此問(wèn)題的解決辦法就是每次監(jiān)聽到有鍵按下缴守,獲取div的文本值(div.text())葬毫,然后使用replace()方法將獲取到的文本值中的空格替換成 (這塊的替換因?yàn)樵诓檎谊P(guān)鍵字時(shí)要利用正則表達(dá)式,正則表達(dá)式中有 ),再根據(jù)需求中對(duì)關(guān)鍵字的定義進(jìn)行各種匹配與替換屡穗。在顯示的時(shí)候用html()方法讓瀏覽器對(duì)一些標(biāo)簽進(jìn)行轉(zhuǎn)化
第三個(gè)問(wèn)題是當(dāng)輸入中文時(shí)在虛擬按鍵中贴捡,應(yīng)用程序同樣監(jiān)聽按鍵,所以中文輸入時(shí)會(huì)出現(xiàn)來(lái)回跳轉(zhuǎn)村砂,并把中文輸入未結(jié)束的拼音同樣顯示在頁(yè)面上烂斋,此問(wèn)題的原因主要是因?yàn)槲彝ㄟ^(guò)監(jiān)聽按鍵來(lái)判斷內(nèi)容修改,至此未找到能很好解決此問(wèn)題的方法箍镜,畢竟還是前端小白一枚源祈。
這條路走死后,我又回到原項(xiàng)目中色迂,研究其實(shí)現(xiàn)原理香缺,和該原理出現(xiàn)的bug
原項(xiàng)目中實(shí)現(xiàn)的原理,大邏輯是使用angularjs將一個(gè)輸入框和div綁定歇僧,輸入框使用ng-bind將值傳遞給應(yīng)用程序控制器图张,之后對(duì)輸入框的值進(jìn)行處理(關(guān)鍵字實(shí)現(xiàn)高亮),然后將div添加ng-bind-html屬性(用于顯示關(guān)鍵字高亮的內(nèi)容)诈悍,最后將改變后的內(nèi)容顯示在界面
在這過(guò)程中祸轮,讓輸入框中的內(nèi)容透明,在輸入框中的上層有div侥钳,用戶看到的是div顯示出來(lái)的帶有高亮的內(nèi)容适袜,但是實(shí)際操作的是下面被設(shè)置為透明顏色的輸入框
在此方法的實(shí)現(xiàn)過(guò)程中,會(huì)出現(xiàn)三個(gè)bug
第一舷夺、當(dāng)輸入中文時(shí)苦酱,虛擬輸入內(nèi)容不顯示,看不到輸入的拼英给猾,只有字疫萤,分析出現(xiàn)此問(wèn)題的原因是因?yàn)檩斎肟蚝蚫iv進(jìn)行綁定是值的綁定,所以當(dāng)輸入中文時(shí)敢伸,只有我們的值才會(huì)被傳遞扯饶,拼英不會(huì)顯示
第二、因?yàn)檩斎肟虻淖煮w間隔和div中顯示的字體間隔不一樣,當(dāng)輸入過(guò)多內(nèi)容的時(shí)候尾序,輸入框的光標(biāo)會(huì)和div輸入的值重疊(雖然輸入框的內(nèi)容設(shè)置為透明钓丰,但光標(biāo)還可以看見,所以div是沒(méi)有光標(biāo)的每币,是用input光標(biāo)斑粱,div的內(nèi)容)
第三、當(dāng)用戶在輸入一段值后又想在中間插入值時(shí)脯爪,這時(shí)又出現(xiàn)了問(wèn)題,input輸入框的光標(biāo)會(huì)動(dòng)來(lái)動(dòng)去矿微,這時(shí)input框中光標(biāo)位置的字符和div給用戶肉眼看到的光標(biāo)前的字符是不一樣的痕慢,這樣就會(huì)出現(xiàn)偏差,刪除的和用戶認(rèn)為刪除的不是同一個(gè)
那么本著先修改掉此類問(wèn)題的想法涌矢,開始了又一次探索
首先因?yàn)樾枨笥衷黾恿藫Q行要求掖举,所以我將輸入框(input)換成了textarea,其次我沒(méi)有使用angular進(jìn)行兩個(gè)數(shù)據(jù)的綁定和監(jiān)聽,我使用了綁定input事件對(duì)輸入框進(jìn)行監(jiān)聽娜庇,每次獲得輸入框中的值塔次,這樣當(dāng)輸入中文時(shí)同樣會(huì)獲得值顯示在div上,其他設(shè)置都是為了讓textarea和div盡量保持一致名秀。
對(duì)于關(guān)鍵字的高亮励负,實(shí)現(xiàn)原理就是通過(guò)正則表達(dá)式把所有的匹配原則先通過(guò)正則表示出來(lái),之后利用replace()方法進(jìn)行替換
replace()方法傳遞的兩個(gè)參數(shù)匕得,第一個(gè)參數(shù)是正則继榆,第二個(gè)參數(shù)同樣可以是個(gè)函數(shù),函數(shù)內(nèi)的參數(shù)同樣可以幫助我們?nèi)ミM(jìn)行一些比較復(fù)雜的替換機(jī)制