在 Algolia Autocomplete Github 上,自述文件说:“填充自动完成结果的数据称为源。您可以在源中使用您想要的任何内容...”。然而,我发现除了 Algolia 之外,几乎没有任何关于使用数据源的文档,而且无论有什么文档,都是模糊的。一旦你投入了几个小时,你就会意识到这实际上是一个诱饵和转换。有人向您承诺了一个可以与任何数据源一起使用的自动完成组件,但您发现整个事情的设计目的就是让您只能使用 Algolia。
看,我想做的就是在 Laravel 10 中创建一个 REST 端点并返回一些虚拟数据。例如:
routes/api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/
Route::get('/test', [TestController::class, 'index']);
app/Http/Controllers/TestController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TestController extends Controller
{
public function index(Request $request)
{
$results = [
'results' => [
['apple'],
['banana'],
['strawberry']
]
];
return response()->json($results);
}
}
通过 JS Fetch 向 API 端点发送 GET 请求:
http://localhost/api/test
回应:
注意:我不知道这是否是正确的格式。我找不到这方面的任何文档!
{
"results":[
[
"apple"
],
[
"banana"
],
[
"strawberry"
]
]
}
这是 Algolia 样板:
<div id="autocomplete"></div>
import { autocomplete } from '@algolia/autocomplete-js';
import '@algolia/autocomplete-theme-classic';
autocomplete({
container: '#autocomplete',
placeholder: 'Search for products',
getSources() {
// What goes here instead of returning an empty array?
return [];
},
});
经过一番尝试和错误,我找到了答案。
这是一个静态示例:
autocomplete({
container: '#autocomplete',
placeholder: 'Search for fruit',
getSources({ query }) {
return [
{
sourceId: 'suggestions',
getItems() {
return [
{
name: 'apple'
},
{
name: 'banana'
},
{
name: 'strawberry'
}
].filter(({ name }) =>
name.toLowerCase().includes(query.toLowerCase())
);
},
templates: {
item({ item }) {
return `${item.name}`;
},
noResults() {
return 'No fruit matching.';
},
},
},
];
},
});
REST 端点自动完成功能类似于:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class TestController extends Controller
{
public function index(Request $request)
{
$validator = Validator::make($request->all(), [
'query' => 'required'
]);
if ($validator->fails()) {
return response()->json([
'status' => 'error',
'message' => 'Invalid request.'
], 400);
}
$query = $request->input('query');
$fruits = collect([
['name' => 'apple'],
['name' => 'banana'],
['name' => 'strawberry']
])->filter(function ($item) use ($query) {
// Similar to "SELECT * FROM table WHERE column LIKE 'foo%';".
return str_starts_with($item['name'], $query);
});
$results = [];
foreach ($fruits as $fruit) {
$results[] = $fruit;
}
return response()->json([
'results' => $results
]);
}
}
autocomplete({
container: '#autocomplete',
placeholder: 'Search for fruit',
getSources({ query }) {
return [
{
sourceId: 'suggestions',
getItems() {
return fetch('/api/test?query=' + encodeURIComponent(query))
.then(response => response.json())
.then(data => {
return data.results;
})
.catch(error => {
return [];
});
},
templates: {
item({ item }) {
return `${item.name}`;
},
noResults() {
return 'No results matching.';
},
},
},
];
},
});