幕思城>電商問答>淘寶規(guī)則>支持英文/漢字/emoji長度計算的輸入框?qū)崿F(xiàn)

    支持英文/漢字/emoji長度計算的輸入框?qū)崿F(xiàn)

    幕思城_北辰樓主|2022-10-27|17:07|發(fā)布在分類 / 淘寶規(guī)則|閱讀:76

    后臺用戶輸入是平臺獲取用戶信息的重要途徑,也是用戶自我表達的重要方式,尤其是在社區(qū)商業(yè)場景下。

    輸入過程的流暢性、準確性和豐富性是我們要保證的重點。

    下圖是近期的產(chǎn)品需求。

    在“圈內(nèi)好物”部分下,允許用戶定義“商品分組”。

    產(chǎn)品與設計專業(yè)的學生有兩個核心訴求:明確的任務目標:對于輸入的字數(shù)限制,首先想到的是原生maxlength參數(shù)。

    的傳統(tǒng)maxlength參數(shù)控制輸入框的最大輸入長度。

    在限制輸入字符的同時,還具有良好的交互體驗,可以截斷超過長度的輸入內(nèi)容。

    但是maxlength不出所料,分不清中英文字符的長度。

    再次嘗試表情符號。

    看了MDN文檔。

    原來maxlength限制了字符串的編碼長度。

    要解釋上面的問題,我們先來了解一下Unicode的字符點。

    在Unicode中,字符由U+_hhhhhh _六位十六進制小數(shù)點表示。

    Unicode也把連續(xù)的65,536個字符點作為一個字符平面,比如U U+000000-U+00FFFF作為平面0。

    而我們常用的中英文文本字符就編碼在這個區(qū)域。

    Javascript字符串以UTF-16編碼,由一系列16位字節(jié)組成。

    這里可以注意到,常用的字符(U U+000000-U+00FFFF)都可以用一個16位字節(jié)來表示。

    這就解釋了為什么在傳統(tǒng)的maxlength計算中,漢字和英文的編碼長度是一樣的。

    對于常用字符,Unicode定義了便于區(qū)分的部分。

    比如字符點的范圍U+4E00-U+9FFF是CJK統(tǒng)一表意文字,我們可以根據(jù)字符點的范圍直接計算長度。

    表情符號編碼比較特殊。

    表情符號存在于平面1(U+010000-U+01FFFF),所以不能直接用一個字符點來表示。

    在UTF-16編碼中,表情符號由代理對編碼。

    比如Unicode代碼是U+1F600,在Javascript代碼中是由0xD83D 0xDE00組成的。

    對于字符串處理,人們通常會想到使用charCodeAt()。

    但是charCodeAt()獲取的是index對應的UTF-16碼,所以無法獲取的碼位碼。

    幸運的是,Javascript提供了codePointAt(),它可以識別代理對并獲得正確的代碼。

    如果用codePointAt(),好像就能分辨表情符號了吧?。

    上圖所示的國旗和家庭表情符號屬于組合表情符號(復合表情符號)。

    與普通表情符號不同的是,組合表情符號的編碼更加復雜,第一次學習這個我感到非常驚訝。

    編碼方法涉及特殊字符U+200D,也稱為零寬度Joiner,ZWJ),以及表情符號修飾符(Emoji Modifier)。

    下面舉幾個例子:在這樣“混亂”的環(huán)境下,有什么通用的解決方法嗎?在網(wǎng)上搜了一下,最后用社區(qū)里比較成熟的表情符號regex來識別表情符號。

    最后總結(jié)長度計算的解決方法:3。

    求和并計算文本的總長度。

    處理文本的自動截斷完成了字符串的長度計算,然后我們要解決自動截斷的問題。

    當用戶輸入超過限制長度的文本時,我需要自動截斷。

    經(jīng)過多次參照maxlength的交互處理,我列舉了以下兩種情況:OnInput提供的inputEvent包含一個inputType類型,用來區(qū)分不同的輸入事件。

    我可以根據(jù)事件類型處理各種情況嗎?但實際調(diào)查表明,inputType的類型遠比想象的復雜,所有處理的成本都非常大。

    復雜性是一個問題,不同瀏覽器容器環(huán)境的兼容性是另一個問題。

    比如在閑魚的android webView中,因為不支持insertReplacementText事件,所以所有的insertReplacementText事件都會被insertText事件替換,這是一個很頭疼的問題。

    粘貼,這種情況下只會觸發(fā)insertText事件,無法獲取刪除的文本" _ width = " 677 px " src = "/202208/24/16613461682159570 . jpg & wx from = 5 & wx _ lazy = 1 & wx _ co = 1 " cross origin = " anonymous " alt = padding:0px;大綱:0px最大寬度:100%;垂直對齊:底部;行高:1.75;邊框-半徑:4px顯示:塊;框尺寸:邊框-框!重要;溢出-換行:斷字!重要;身高:自動!重要;寬度:677px!重要;能見度:可見!重要;”>所以又回到了那個問題:有沒有一個通用的解決方案?既然inputType不可靠,我們能不能直接處理oninput事件的更新文本(值)?作為基本事件,至少兼容性沒有問題。

    這里的方案是獲取oninput事件的值,然后用上次的舊文本做一個Diff,最后根據(jù)Diff的結(jié)果進行處理。

    在Diff計算中,我們考慮三種情況:最后,構造Diff結(jié)果。

    如果用戶輸入的總長度大于指定長度,那么我們可以基于insertChunk截取它。

    這樣可以在一定程度上減輕對inputType的依賴。

    但是還有幾個問題需要提一下。

    3.1 IOS拼音輸入在maxlength的截斷交互中,用戶輸入漢語拼音結(jié)合中文(排版)時沒有限制。

    在用戶完成拼音到中文組合的輸入后,根據(jù)組合的文本長度對其進行截斷。

    在IOS下,輸入組件提供compositionend的監(jiān)聽事件。

    當用戶輸入拼音時,inputEvent的inputType事件的名稱是insertCompositionText。

    所以當用戶輸入時,我們可以先忽略這個事件,然后在compositionend事件被觸發(fā)時處理文本。

    3.2事件之上的其他不兼容解決方案已經(jīng)可以支持大部分用戶輸入交互。

    但是,仍然有一些不兼容的事件,比如撤銷/重做。

    這些事件將在截斷前恢復原始文本,并與截斷邏輯沖突。

    考慮到移動用戶不常使用撤銷/重做等操作,這里可以屏蔽撤銷/重做事件。

    掩碼回調(diào)在beforeinput事件中處理,您可以使用preventDefault()來阻止下一個輸入事件。

    因為還有很多類型的inputType事件,所以我們這次沒有全部測試。

    如果以后遇到一些不兼容的事件,也可以考慮直接屏蔽,保證基本的輸入功能,不影響用戶交互。

    Demo & code片段文本長度計算代碼這里不具體給出,一般邏輯如下 文本比較代碼:這里提供了文本比較的代碼。

    這里的比較邏輯比較簡單,因為處理用戶輸入,比較結(jié)果必須是(1)整塊插入,(2)整塊刪除,(3)整塊替換中的一個。

    在對輸入的事件處理的總結(jié)的道路上,有許多曲折。

    最后終于做出了滿意的組件。

    在這個過程中,我了解了Javascript字符串和Unicode編碼,尤其是emoji編碼,真的很有趣。

    這個輸入框的方案也解決了一個困擾前端輸入框的難題,希望能給大家?guī)硪恍﹩l(fā)。

    reference https://www . Unicode . org/reports/tr11/https://en . Wikipedia . org/wiki/Plane _(Unicode)# Supplementary _ Multilingual _ Plane https://thekevinscott.com/emojis-in-javascript/ https://en . Wikipedia . org/wiki/CJK _統(tǒng)一_表意文字_(Unicode_block)

    這個問題還有疑問的話,可以加幕.思.城火星老師免費咨詢,微V.信X號是為: msc496。

    淘寶店運營問題沒解決?沒思路?想系統(tǒng)學習? 馬上點這里加火星老師微信【無償贈送5.5G運營禮包、電商軟件VIP賬號、內(nèi)部課程等資源】
    >
    發(fā)表評論

      微信掃碼回復「666