Google Places Autocomplete 输入尾随空格后建议为何消失?
数据小许
结论
从给出的代码看,尾随空格不应改变实际发送的查询。事件处理器用 input.value.trim() 检查长度,并将处理后的值传给 API,所以添加或删除尾随空格时,发送的 input 通常相同。列表在失焦后重新出现,问题可能出在页面的显示状态。如果连续输入触发了多个请求,较早返回的响应也可能覆盖新结果。仅凭这段代码无法确定具体原因,可以检查浏览器开发者工具中的网络请求和控制台错误。
先检查列表是否被隐藏
输入框聚焦时,代码会移除列表的 hidden 类;点击输入框和列表之外时,则会添加这个类。输入事件处理器不会主动移除 hidden。因此,如果输入时列表已隐藏,API 请求不会让它重新显示。重新聚焦后列表再次出现,和这个行为相符。
可以在渲染结果时明确显示列表,并在查询过短或没有结果时更新列表内容,避免保留旧状态。下面的示例还会取消前一个请求,防止响应乱序时旧结果覆盖新结果:
let currentController;
async function autocomplete(query, signal) {
const response = await fetch(
"https://places.googleapis.com/v1/places:autocomplete",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Goog-Api-Key": API_KEY
},
body: JSON.stringify({ input: query }),
signal
}
);
if (!response.ok) {
throw new Error(`Autocomplete 请求失败:${response.status}`);
}
const data = await response.json();
return data.suggestions ?? [];
}
const input = document.querySelector("#address");
const results = document.querySelector("#results");
input.addEventListener("input", async () => {
const query = input.value.trim();
results.classList.remove("hidden");
currentController?.abort();
if (query.length < 3) {
results.replaceChildren();
const message = document.createElement("li");
message.textContent = "Please enter at least 3 characters";
results.appendChild(message);
return;
}
const controller = new AbortController();
currentController = controller;
try {
const suggestions = await autocomplete(query, controller.signal);
// 请求期间输入内容可能已改变,忽略过期响应。
if (query !== input.value.trim()) return;
results.replaceChildren();
if (suggestions.length === 0) {
const message = document.createElement("li");
message.textContent = "No results found";
results.appendChild(message);
return;
}
for (const suggestion of suggestions) {
const li = document.createElement("li");
li.textContent = suggestion.placePrediction?.text?.text ?? "";
li.dataset.action = "select-address";
results.appendChild(li);
}
} catch (error) {
if (error.name === "AbortError") return;
console.error(error);
}
});
这里的 API_KEY 是从安全配置中读取的密钥。不要把真实 API key 放在公开的前端代码中。如果示例里的密钥是真实可用的,应尽快轮换,并限制它可使用的 API 和来源。
检查 HTML 结构
示例把 <input> 和 <ul> 放在 <button> 里面。button 不应包含其他交互元素,可以移除外层按钮,改用普通容器并按需要设置样式。例如:
<div class="address-container">
<input
type="text"
id="address"
placeholder="Enter address"
class="address"
autocomplete="off"
>
<ul id="results" class="address-suggestion hidden">
<li class="three">Please enter at least 3 characters</li>
</ul>
</div>
如何确认原因
在开发者工具的 Network 面板中,分别查看添加和删除空格时是否都发出了请求,并检查请求体中的 input、HTTP 状态码和响应内容。如果网络响应正常但列表不可见,检查 hidden 类和 CSS;如果多个请求的返回顺序与输入顺序不同,可以使用上面的取消请求和过期响应检查。也要确认 API key 和 Places API 配置有效。
备注:内容仅供参考。
