如何在Autocomplete组件中聚焦/失焦时显示不同值
我完全懂你遇到的麻烦——每次都要手动删掉描述才能回到只显示ID的状态,确实太麻烦了。咱们可以通过状态管理和事件监听来实现自动切换,同时保留根据ID和描述筛选的功能,下面是具体的实现方案:
核心实现思路
- 单独维护选中项的完整数据(不要只存显示的文本),这样能随时切换显示格式
- 监听输入框的
focus和blur事件,自动切换显示内容:失焦时显示ID - 描述,聚焦时只显示ID - 自定义筛选逻辑,同时支持根据ID和描述匹配建议项(比如输入
1能匹配到1、10、1010这类包含1的ID项)
原生JavaScript实现示例
适合不需要框架的场景,逻辑清晰易懂:
<div style="position: relative; width: 300px;"> <input type="text" id="autoInput" placeholder="输入ID或描述" style="width: 100%; padding: 8px;" > <ul id="suggestions" style="position: absolute; top: 35px; left: 0; right: 0; margin: 0; padding: 0; list-style: none; border: 1px solid #ddd; background: white; max-height: 200px; overflow-y: auto;" ></ul> </div> <script> // 模拟业务数据 const suggestionItems = [ { id: '1', desc: 'item01' }, { id: '10', desc: 'item10' }, { id: '1010', desc: 'item1010' }, { id: '2', desc: 'item02' }, { id: '3', desc: 'item03' } ]; const input = document.getElementById('autoInput'); const suggestionsList = document.getElementById('suggestions'); let selectedItem = null; // 存储选中的完整项,用于切换显示格式 // 渲染筛选后的建议列表 function renderSuggestions(filterText) { suggestionsList.innerHTML = ''; // 自定义筛选:匹配ID或描述(忽略大小写) const filteredItems = suggestionItems.filter(item => item.id.toLowerCase().includes(filterText.toLowerCase()) || item.desc.toLowerCase().includes(filterText.toLowerCase()) ); filteredItems.forEach(item => { const li = document.createElement('li'); li.style.padding = '8px'; li.style.cursor = 'pointer'; li.style.borderBottom = '1px solid #eee'; li.textContent = `${item.id} - ${item.desc}`; // 点击选中项 li.addEventListener('click', () => { selectedItem = item; input.value = `${item.id} - ${item.desc}`; // 失焦状态的显示格式 suggestionsList.innerHTML = ''; }); suggestionsList.appendChild(li); }); } // 聚焦事件:切换为仅显示ID input.addEventListener('focus', () => { if (selectedItem) { input.value = selectedItem.id; // 聚焦后自动渲染匹配当前ID的建议 renderSuggestions(selectedItem.id); } }); // 失焦事件:切换为ID+描述格式 input.addEventListener('blur', () => { if (selectedItem) { input.value = `${selectedItem.id} - ${selectedItem.desc}`; } }); // 输入时实时筛选 input.addEventListener('input', (e) => { const inputText = e.target.value; renderSuggestions(inputText); // 如果输入的是纯ID,自动匹配对应项 const matchedItem = suggestionItems.find(item => item.id === inputText); if (matchedItem) { selectedItem = matchedItem; } else { // 输入不匹配任何ID时,清空选中状态 selectedItem = null; } }); </script>
React + Material-UI实现示例
如果用React生态,Material-UI的Autocomplete组件可以这样自定义:
import React, { useState } from 'react'; import Autocomplete from '@mui/material/Autocomplete'; import TextField from '@mui/material/TextField'; // 模拟业务数据 const suggestionItems = [ { id: '1', desc: 'item01' }, { id: '10', desc: 'item10' }, { id: '1010', desc: 'item1010' }, { id: '2', desc: 'item02' } ]; export default function DynamicDisplayAutocomplete() { const [selectedItem, setSelectedItem] = useState(null); const [inputValue, setInputValue] = useState(''); return ( <Autocomplete options={suggestionItems} // 内部用ID作为项的唯一标识 getOptionLabel={(option) => option.id} inputValue={inputValue} // 处理输入变化 onInputChange={(event, newInputValue) => { setInputValue(newInputValue); // 尝试匹配输入值对应的项(支持ID或完整格式) const matched = suggestionItems.find(item => item.id === newInputValue || `${item.id} - ${item.desc}` === newInputValue ); if (matched) setSelectedItem(matched); }} // 处理选中项变化 onChange={(event, newValue) => { setSelectedItem(newValue); if (newValue) { // 选中后默认显示ID+描述格式 setInputValue(`${newValue.id} - ${newValue.desc}`); } }} // 自定义输入框的聚焦/失焦行为 renderInput={(params) => ( <TextField {...params} label="输入ID或描述" variant="outlined" onFocus={() => { // 聚焦时切换为仅显示ID if (selectedItem) setInputValue(selectedItem.id); }} onBlur={() => { // 失焦时切换为ID+描述格式 if (selectedItem) setInputValue(`${selectedItem.id} - ${selectedItem.desc}`); }} /> )} // 自定义筛选逻辑,同时匹配ID和描述 filterOptions={(options, state) => { const query = state.inputValue.toLowerCase(); return options.filter(option => option.id.toLowerCase().includes(query) || option.desc.toLowerCase().includes(query) ); }} /> ); }
关键细节说明
- 状态分离:一定要把「显示文本」和「选中项数据」分开存储,不能只依赖输入框的文本,否则切换显示格式时会丢失原始数据
- 筛选逻辑:自定义筛选时要同时检查ID和描述,确保输入ID时能匹配到所有包含该ID的项(比如输入
1会显示1、10、1010) - 事件同步:聚焦/失焦时要确保输入框的值和选中项同步,避免出现显示内容和实际选中数据不一致的情况
内容的提问来源于stack exchange,提问作者TadeM
相关产品推荐
相关产品推荐

