是否存在不依赖于任何其他库的javascript自动完成库?
我没有使用jQuery或者喜欢,因为我正在制作一个我需要保持额外光线的移动应用。
答案 0 :(得分:24)
Here是一个基本的JavaScript示例,可以将其修改为自动完成控件:
<input type="text" onkeyup="changeInput(this.value)">
<div id="result"></div>
var people = ['Steven', 'Sean', 'Stefan', 'Sam', 'Nathan'];
function matchPeople(input) {
var reg = new RegExp(input.split('').join('\\w*').replace(/\W/, ""), 'i');
return people.filter(function(person) {
if (person.match(reg)) {
return person;
}
});
}
function changeInput(val) {
var autoCompleteResult = matchPeople(val);
document.getElementById("result").innerHTML = autoCompleteResult;
}
答案 1 :(得分:16)
对于那些在2017年以后需要一个简单解决方案的人来说,您可以使用HTML5的内置DefInt = function(y) { integrate(function(x) { (y-1)*x*x },0,y)$value }
optimize(DefInt, c(-2,2))
$minimum
[1] 0.7499972
$objective
[1] -0.03515625
代码,而不是依赖JavaScript。
示例:
<datalist>
请注意,这在Safari中不起作用(截至2017年4月)。
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist
答案 2 :(得分:8)
自动完成脚本的核心是对术语词典的ajax调用。
我认为您的移动应用程序已经包含了ajax功能,所以也许您最好从头开始编写自动完成功能?基本上你只需要输入标签,触发ajax调用的keyup事件处理程序和收集响应的div。
[更新]根据评论,来自John Resig博客的一些参考文献:
答案 3 :(得分:1)
ES2016功能:Array.prototype.includes
,无需外部库。
function autoComplete(Arr, Input) {
return Arr.filter(e =>e.toLowerCase().includes(Input.toLowerCase()));
}
答案 4 :(得分:0)
前一天我正在研究这个问题,而我的解决方案最初就像这里的ES6解决方案一样,
return this.data.filter((option) => {
return option.first_name
.toString()
.toLowerCase()
.indexOf(this.searchTerms.toLowerCase()) >= 0
})
但是问题在于它不够强大,无法处理过滤嵌套数据。您可以看到它正在过滤this.data
,其数据结构如下:
[
{ first_name: 'Bob', },
{ first_name: 'Sally', },
]
在将搜索词和this.searchTerms
都设置为小写之后,您可以看到它基于option.first_name
进行过滤,但是搜索option.user.first_name
过于严格。我最初的尝试是在该字段中进行过滤,例如:
this.field = 'user.first_name';
但这涉及到野蛮的自定义JavaScript,以处理this.field.split('.')
之类的内容并动态生成过滤器功能。
相反,我想起了以前使用过的旧库,名为fuse.js
,它运行良好,因为它不仅可以处理我刚才称为this.field
的任意嵌套的情况,还可以处理基于定义阈值的模糊匹配。
在这里签出:https://fusejs.io/
[编辑说明]:我意识到这个问题正在寻找没有外部图书馆的问题,但是我希望将其保留在此处,因为它提供了相邻的价值。它并非旨在成为“解决方案”。
这是我目前的使用方式:
import Fuse from 'fuse.js';
const options = {
threshold: 0.3,
minMatchCharLength: 2,
keys: [this.field],
};
const fuse = new Fuse(this.data, options);
this.filteredData = fuse.search(this.searchTerms);
您将必须阅读Fuse文档以更好地理解它,但从根本上,您可以看到使用要过滤的数据和选项创建了new Fuse()
对象。
keys: [this.field]
部分很重要,因为这是您传递要搜索的键的地方,并且可以传递它们的数组。例如,您可以按this.data
过滤keys: ['user.first_name', 'user.friends.first_name']
。
我目前在Vue JS中使用此代码,因此我在实例watch
函数中拥有上述逻辑,因此每次this.searchTerms
更改时,该逻辑就会运行并更新this.filteredData
放在我的自动填充组件的下拉列表中。
也很抱歉,我只是意识到这个问题专门针对没有外部库的问题,但是无论如何我都会发布此问题,因为每次我在Vue JS或React JS中使ES6自动完成时都会发现此问题。我认为进行严格或松散的模糊匹配并支持任意嵌套的数据非常有价值。 fuse.js
基于Webpack捆绑分析器,压缩后为4.1kb,因此它很小,因为它可以支持“所有”客户端过滤需求。
如果使用外部库的能力有限,请考虑我的第一个示例代码。如果您的数据结构是静态的,则可以使用它,并且如果您希望对搜索到的字段进行可变化(即:如果您的对象始终是平坦的),则可以轻松地将option.first_name
更改为option[this.field]
之类的内容。
您也可以使列表可变以进行搜索。尝试这样的事情:
const radicalFilter = ({ collection, field, searchTerms }) => {
return collection.filter((option) => {
return option[field]
.toString()
.toLowerCase()
.indexOf(searchTerms.toLowerCase()) >= 0
})
}
radicalFilter({
collection: [{ first_name: 'Bob' }, { first_name: 'Sally' }],
field: 'first_name',
searchTerms: 'bob',
})
根据我过去几年的经验,以上示例非常出色。我已经使用它过滤了react-table
组件中的10,000条记录,但并没有费劲。它不会创建任何额外的中间数据结构。只是Array.prototype.filter()
会接收您的数组并返回带有匹配项的新数组。
答案 5 :(得分:-1)
我通过向服务器发送JSON请求并使用Python代码执行自动完成来完成此操作。它有点慢,但它保存了大量的数据。