You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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)
        );
      }}
    />
  );
}
关键细节说明
  1. 状态分离:一定要把「显示文本」和「选中项数据」分开存储,不能只依赖输入框的文本,否则切换显示格式时会丢失原始数据
  2. 筛选逻辑:自定义筛选时要同时检查ID和描述,确保输入ID时能匹配到所有包含该ID的项(比如输入1会显示1、10、1010)
  3. 事件同步:聚焦/失焦时要确保输入框的值和选中项同步,避免出现显示内容和实际选中数据不一致的情况

内容的提问来源于stack exchange,提问作者TadeM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:33:45