jquery-textcomplete输入首个词汇后无法正确匹配后续词汇的问题
问题分析与解决
我帮你排查了这个问题,核心原因出在你使用的正则表达式上,导致插件无法识别空格后的单词前缀。
为什么会出现这个问题?
你写的正则/(^|\S*)([^\u0000-\u007f]{2,}|\w{2,})$/里,(^|\S*)这部分是匹配文本开头或者任意非空白字符的连续序列。当你输入apple加空格后,再输入app,此时光标前的文本是apple app,这个正则会先匹配空格前的apple(因为\S*只认非空白字符),而空格后的app因为前面有空格,无法和正则里的第二个捕获组衔接,导致整个正则匹配失败,插件也就不会触发补全。
至于你说输入appe能出结果,大概率是测试时的小误差——如果严格按照apple 加appe的步骤,其实也会遇到同样的问题,只是可能你输入时不小心没加空格,或者插件的匹配逻辑有细微的容错,但本质问题还是正则不支持空格后的单词匹配。
怎么解决?
我们需要修改正则,让它能精准匹配文本末尾的最后一个单词前缀(不管前面有没有空格),同时调整捕获组的索引:
修正后的代码
$('#textcomplete').textcomplete([{ words: ['тоҷик', 'оҷиз', 'ҷило', 'тоҷ', 'тоҷикистон', 'apple', 'please', 'app', 'perl', 'person', 'erlan'], // 新正则:匹配开头或空格后的至少2个目标字符 match: /(?:^|\s)([^\u0000-\u007f]{2,}|\w{2,})$/, search: function(term, callback) { callback($.map(this.words, function(word) { if (word.indexOf(term.toLocaleLowerCase()) !== 0) return null; if (term[term.length-1] === term[term.length-1].toLocaleUpperCase()) return word.toLocaleUpperCase(); if (term[0] === term[0].toLocaleUpperCase()) return word.charAt(0).toLocaleUpperCase() + word.slice(1); return word; })); }, // 捕获组从2改成1,因为现在用第一个捕获组取前缀 index: 1, replace: function(word) { return word + ' '; } }]);
关键修改点
- 正则表达式:
(?:^|\s)用来匹配文本开头或者任意空格(用?:标记为非捕获组,避免干扰捕获组索引),后面的捕获组专门抓取我们需要补全的前缀。 - 捕获组索引:原来的
index:2改成index:1,因为现在我们用第一个捕获组来获取待补全的term。
测试效果
现在再按你的步骤测试:
- 输入
app,正常显示app和apple - 选择
apple后文本变成apple - 再次输入
app,插件会立刻显示对应的补全选项 - 非ASCII词汇比如
то也能正常触发补全
这样就完美解决了空格后无法匹配的问题啦!
内容的提问来源于stack exchange,提问作者Andreas Hunter
相关产品推荐
相关产品推荐

