输入时实时更新Select2搜索值的拉丁转西里尔字符替换异常问题
问题根源
你遇到的最后输入字符不生效的问题不是函数延迟,原因有两个:
- Select2内部的搜索逻辑触发时机早于你绑定的
keyup事件:当你按下按键输入字符时,Select2已经先用原始的拉丁字符完成了搜索匹配,你后续在keyup里替换成西里尔字符后,没有通知Select2重新执行搜索,所以搜索结果看起来还是基于之前的输入内容 - 你的转换规则存在笔误:大写G的替换规则写错为输出
Р,正确应该输出Г
修复方案
你可以按以下修改代码:
- 把事件从
keyup换成input事件,覆盖所有输入场景(包括粘贴、自动填充等) - 替换完输入框内容后,手动触发Select2的搜索更新
修改后的核心代码如下:
$("#city").select2({ width: "100%", allowClear: true, placeholder: "-- изберете град --" }); $(document).on("focus", ".select2-search__field", function () { $(this).attr("autocomplete", "12525dcd27fc636c05a033507e1f2fdd"); }); // 把keyup改成input事件 $(document).on("input", ".select2-search__field", function () { var b = $(this).val(); // 修正大写G的替换错误,原规则的Р改为Г b = b.replace(/q/g, "я").replace(/w/g, "в").replace(/e/g, "е").replace(/r/g, "р").replace(/t/g, "т").replace(/y/g, "ъ").replace(/u/g, "у").replace(/i/g, "и").replace(/o/g, "о").replace(/p/g, "п").replace(/a/g, "а").replace(/s/g, "с").replace(/d/g, "д").replace(/f/g, "ф").replace(/g/g, "г").replace(/h/g, "х").replace(/j/g, "й").replace(/k/g, "к").replace(/l/g, "л").replace(/z/g, "з").replace(/x/g, "ь").replace(/c/g, "ц").replace(/v/g, "ж").replace(/b/g, "б").replace(/n/g, "н").replace(/m/g, "м").replace(/\`/g, "ч").replace(/\[/g, "ш").replace(/\]/g, "щ").replace(/\\/g, "ю").replace(/Q/g, "Я").replace(/W/g, "В").replace(/E/g, "Е").replace(/R/g, "Р").replace(/T/g, "Т").replace(/Y/g, "Ъ").replace(/U/g, "У").replace(/I/g, "И").replace(/O/g, "О").replace(/P/g, "П").replace(/A/g, "А").replace(/S/g, "С").replace(/D/g, "Д").replace(/F/g, "Ф").replace(/G/g, "Г").replace(/H/g, "Х").replace(/J/g, "Й").replace(/K/g, "К").replace(/L/g, "Л").replace(/Z/g, "З").replace(/X/g, "Ь").replace(/C/g, "Ц").replace(/V/g, "Ж").replace(/B/g, "Б").replace(/N/g, "Н").replace(/M/g, "М").replace(/\~/g, "Ч").replace(/\{/g, "Ш").replace(/\}/g, "Щ").replace(/\|/g, "Ю"); $(this).val(b); // 手动触发Select2重新搜索 $("#city").trigger("input"); });
可选优化方案
如果你不需要强制把用户输入的拉丁字符转换成西里尔显示在输入框,只是希望用户输入拉丁字符也能匹配到西里尔的城市选项,可以直接自定义Select2的匹配规则,不需要修改输入框内容:
// 预先定义拉丁到西里尔的映射表 const transliterateMap = {q:'я',w:'в',e:'е',r:'р',t:'т',y:'ъ',u:'у',i:'и',o:'о',p:'п',a:'а',s:'с',d:'д',f:'ф',g:'г',h:'х',j:'й',k:'к',l:'л',z:'з',x:'ь',c:'ц',v:'ж',b:'б',n:'н',m:'м',`:'ч', '[':'ш', ']':'щ', '\\':'ю', Q:'Я', W:'В', E:'Е', R:'Р', T:'Т', Y:'Ъ', U:'У', I:'И', O:'О', P:'П', A:'А', S:'С', D:'Д', F:'Ф', G:'Г', H:'Х', J:'Й', K:'К', L:'Л', Z:'З', X:'Ь', C:'Ц', V:'Ж', B:'Б', N:'Н', M:'М', '~':'Ч', '{':'Ш', '}':'Щ', '|':'Ю'}; function latinToCyrillic(str) { return str.split('').map(char => transliterateMap[char] || char).join(''); } $("#city").select2({ width: "100%", allowClear: true, placeholder: "-- изберете град --", matcher: function(params, data) { // 如果搜索词为空,返回所有结果 if ($.trim(params.term) === '') { return data; } // 把搜索词转成西里尔 const searchTerm = latinToCyrillic(params.term.toLowerCase()); // 匹配选项文本 if (data.text.toLowerCase().indexOf(searchTerm) > -1) { return data; } // 不匹配返回null return null; } });
这个方案的好处是用户可以保持自己的输入习惯,不需要输入内容被强制转换,也能正常搜索到目标城市。
内容的提问来源于stack exchange,提问作者Hristo Torbov
相关产品推荐
相关产品推荐

