49

是否有不依赖于任何其他库的 javascript 自动完成库?

我没有使用 jQuery 或类似的东西,因为我正在制作一个需要保持额外光线的移动应用程序。

4

6 回答 6

34

是一个基本的 JavaScript 示例,可以将其修改为自动完成控件:

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;
}
<input type="text" onkeyup="changeInput(this.value)">
<div id="result"></div>

于 2015-02-04T12:13:14.063 回答
31

对于 2017 年以后需要简单解决方案的任何人,您可以使用 HTML5 的内置<datalist>标签而不是依赖 JavaScript。

例子:

<datalist id="languages">
  <option value="HTML">
  <option value="CSS">
  <option value="JavaScript">
  <option value="Java">
  <option value="Ruby">
  <option value="PHP">
  <option value="Go">
  <option value="Erlang">
  <option value="Python">
  <option value="C">
  <option value="C#">
  <option value="C++">
</datalist>

<input type="text" list="languages">

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist

于 2017-04-14T18:55:52.677 回答
9

自动完成脚本的核心是对术语字典的 ajax 调用。

我假设您的移动应用程序已经包含一个 ajax 功能,所以也许您最好从头开始编写您的自动完成功能?基本上,您需要一个输入标记、一个触发 ajax 调用的 keyup 事件处理程序以及一个用于收集响应的 div。

[更新] 根据评论,来自 John Resig 博客的一些参考资料:

http://ejohn.org/blog/revised-javascript-dictionary-search/

http://ejohn.org/blog/jquery-livesearch/

于 2012-07-10T01:57:03.823 回答
2

ES2016 特性:Array.prototype.includes没有外部库。

function autoComplete(Arr, Input) {
    return Arr.filter(e =>e.toLowerCase().includes(Input.toLowerCase()));
}

Codepen 演示

于 2018-09-27T07:43:17.283 回答
0

我通过将 JSON 请求发送回服务器并使用 Python 代码执行自动完成来完成此操作。它有点慢,但它节省了发送大量数据。

于 2012-07-10T00:06:42.257 回答
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 自动完成时都会发现这个问题。我认为有严格或松散的模糊匹配和支持任意嵌套的数据是非常有价值的。基于 Webpack 捆绑分析器,fuse.js压缩后为 4.1kb,因此它非常小,因为它可以支持“所有”客户端过滤需求。

如果您使用外部库的能力有限,请考虑我的第一个示例代码。如果您的数据结构是静态的,它就可以工作,并且您可以轻松地更改option.first_nameoption[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()获取您的数组并返回一个包含匹配项的新数组。

于 2019-10-18T17:21:49.270 回答