前端项目实战叁佰贰拾柒material ui-Autocomplete-自动补全
import React from 'react'; import PropTypes from 'prop-types'; import deburr from 'lodash/deburr'; import Downshift from 'downshift'; import { withStyles } from '@material-ui/core/styles'; import TextField from '@material-ui/core/TextField'; import Popper from '@material-ui/core/Popper'; import Paper from '@material-ui/core/Paper'; import MenuItem from '@material-ui/core/MenuItem'; import Chip from '@material-ui/core/Chip'; const suggestions = [ { label: 'Afghanistan' }, { label: 'Aland Islands' }, { label: 'Albania' }, { label: 'Algeria' }, { label: 'American Samoa' }, { label: 'Andorra' }, { label: 'Angola' }, { label: 'Anguilla' }, { label: 'Antarctica' }, { label: 'Antigua and Barbuda' }, { label: 'Argentina' }, { label: 'Armenia' }, { label: 'Aruba' }, { label: 'Australia' }, { label: 'Austria' }, { label: 'Azerbaijan' }, { label: 'Bahamas' }, { label: 'Bahrain' }, { label: 'Bangladesh' }, { label: 'Barbados' }, { label: 'Belarus' }, { label: 'Belgium' }, { label: 'Belize' }, { label: 'Benin' }, { label: 'Bermuda' }, { label: 'Bhutan' }, { label: 'Bolivia, Plurinational State of' }, { label: 'Bonaire, Sint Eustatius and Saba' }, { label: 'Bosnia and Herzegovina' }, { label: 'Botswana' }, { label: 'Bouvet Island' }, { label: 'Brazil' }, { label: 'British Indian Ocean Territory' }, { label: 'Brunei Darussalam' }, ]; function renderInput(inputProps) { const { InputProps, classes, ref, ...other } = inputProps; return ( <TextField InputProps={{ inputRef: ref, classes: { root: classes.inputRoot, input: classes.inputInput, }, ...InputProps, }} {...other} /> ); } function renderSuggestion({ suggestion, index, itemProps, highlightedIndex, selectedItem }) { const isHighlighted = highlightedIndex === index; const isSelected = (selectedItem || '').indexOf(suggestion.label) > -1; return ( <MenuItem {...itemProps} key={suggestion.label} selected={isHighlighted} component="div" style={{ fontWeight: isSelected ? 500 : 400, }} > {suggestion.label} </MenuItem> ); } renderSuggestion.propTypes = { highlightedIndex: PropTypes.number, index: PropTypes.number, itemProps: PropTypes.object, selectedItem: PropTypes.string, suggestion: PropTypes.shape({ label: PropTypes.string }).isRequired, }; function getSuggestions(value) { const inputValue = deburr(value.trim()).toLowerCase(); const inputLength = inputValue.length; let count = 0; return inputLength === 0 ? [] : suggestions.filter(suggestion => { const keep = count < 5 && suggestion.label.slice(0, inputLength).toLowerCase() === inputValue; if (keep) { count += 1; } return keep; }); } class DownshiftMultiple extends React.Component { state = { inputValue: '', selectedItem: [], }; handleKeyDown = event => { const { inputValue, selectedItem } = this.state; if (selectedItem.length && !inputValue.length && event.key === 'Backspace') { this.setState({ selectedItem: selectedItem.slice(0, selectedItem.length - 1), }); } }; handleInputChange = event => { this.setState({ inputValue: event.target.value }); }; handleChange = item => { let { selectedItem } = this.state; if (selectedItem.indexOf(item) === -1) { selectedItem = [...selectedItem, item]; } this.setState({ inputValue: '', selectedItem, }); }; handleDelete = item => () => { this.setState(state => { const selectedItem = [...state.selectedItem]; selectedItem.splice(selectedItem.indexOf(item), 1); return { selectedItem }; }); }; render() { const { classes } = this.props; const { inputValue, selectedItem } = this.state; return ( <Downshift id="downshift-multiple" inputValue={inputValue} onChange={this.handleChange} selectedItem={selectedItem} > {({ getInputProps, getItemProps, isOpen, inputValue: inputValue2, selectedItem: selectedItem2, highlightedIndex, }) => ( <div className={classes.container}> {renderInput({ fullWidth: true, classes, InputProps: getInputProps({ startAdornment: selectedItem.map(item => ( <Chip key={item} tabIndex={-1} label={item} className={classes.chip} onDelete={this.handleDelete(item)} /> )), onChange: this.handleInputChange, onKeyDown: this.handleKeyDown, placeholder: 'Select multiple countries', }), label: 'Label', })} {isOpen ? ( <Paper className={classes.paper} square> {getSuggestions(inputValue2).map((suggestion, index) => renderSuggestion({ suggestion, index, itemProps: getItemProps({ item: suggestion.label }), highlightedIndex, selectedItem: selectedItem2, }), )} </Paper> ) : null} </div> )} </Downshift> ); } } DownshiftMultiple.propTypes = { classes: PropTypes.object.isRequired, }; const styles = theme => ({ root: { flexGrow: 1, height: 250, }, container: { flexGrow: 1, position: 'relative', }, paper: { position: 'absolute', zIndex: 1, marginTop: theme.spacing.unit, left: 0, right: 0, }, chip: { margin: `${theme.spacing.unit / 2}px ${theme.spacing.unit / 4}px`, }, inputRoot: { flexWrap: 'wrap', }, inputInput: { width: 'auto', flexGrow: 1, }, divider: { height: theme.spacing.unit * 2, }, }); let popperNode; function IntegrationDownshift(props) { const { classes } = props; return ( <div className={classes.root}> <Downshift id="downshift-simple"> {({ getInputProps, getItemProps, getMenuProps, highlightedIndex, inputValue, isOpen, selectedItem, }) => ( <div className={classes.container}> {renderInput({ fullWidth: true, classes, InputProps: getInputProps({ placeholder: 'Search a country (start with a)', }), })} <div {...getMenuProps()}> {isOpen ? ( <Paper className={classes.paper} square> {getSuggestions(inputValue).map((suggestion, index) => renderSuggestion({ suggestion, index, itemProps: getItemProps({ item: suggestion.label }), highlightedIndex, selectedItem, }), )} </Paper> ) : null} </div> </div> )} </Downshift> <div className={classes.divider} /> <DownshiftMultiple classes={classes} /> <div className={classes.divider} /> <Downshift id="downshift-popper"> {({ getInputProps, getItemProps, getMenuProps, highlightedIndex, inputValue, isOpen, selectedItem, }) => ( <div className={classes.container}> {renderInput({ fullWidth: true, classes, InputProps: getInputProps({ placeholder: 'With Popper', }), ref: node => { popperNode = node; }, })} <Popper open={isOpen} anchorEl={popperNode}> <div {...(isOpen ? getMenuProps({}, { suppressRefError: true }) : {})}> <Paper square style={{ marginTop: 8, width: popperNode ? popperNode.clientWidth : null }} > {getSuggestions(inputValue).map((suggestion, index) => renderSuggestion({ suggestion, index, itemProps: getItemProps({ item: suggestion.label }), highlightedIndex, selectedItem, }), )} </Paper> </div> </Popper> </div> )} </Downshift> </div> ); } IntegrationDownshift.propTypes = { classes: PropTypes.object.isRequired, }; export default withStyles(styles)(IntegrationDownshift);
运行结果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南