我想根据用户输入显示建议下拉列表。以下代码可在3种情况下正常工作。
->用户仅输入@ char会显示所有用户建议
-> @,然后出现“ @user”字样,显示使用“ user”过滤的用户建议
->如果@根据光标位置和@之后的字符串(在光标位置过滤用户建议之前)在输入中的任意位置输入@(输入可能包含多个@)。
这可行,但我想进一步简化一下。有人可以帮我吗。谢谢。
class User extends React.PureComponent {
state = {
text: '',
suggestions: [],
};
user_list = [
{name: 'user1'},
{name: 'user2'},
];
handle_input_change = (event) => {
const {value} = event.target;
if (value.includes('@') && value.indexOf('@') === value.length -
1) {
this.setState({
[event.target.name]: value,
suggestions: [...this.user_mention_list],
});
} else if (value.includes('@') && value.length > 1) {
let string_after_at;
if (event.target.selectionStart > value.lastIndexOf('@')) {
string_after_at = value.slice(value.lastIndexOf('@') +
1).toLowerCase();
}
if (event.target.selectionStart <=
event.target.value.indexOf('@') && event.target.selectionStart
<= event.target.value.lastIndexOf('@')) {
this.setState({
[event.target.name]: value,
suggestions: [],
});
}
if (event.target.selectionStart > value.indexOf('@') &&
event.target.selectionStart <= value.lastIndexOf('@')) {
let string_after_cursor_position =
value.substr(event.target.selectionStart, value.length -
1).split(' ')[0];
if (string_after_cursor_position.startsWith('@')) {
string_after_cursor_position = '';
}
const string1 = value.substr(0,
event.target.selectionStart);
const string_from_at =
string1.slice(string1.lastIndexOf('@') + 1);
string_after_at = string_from_at +
string_after_cursor_position ;
}
const new_suggestions = this.user_mention_list.filter(user =>
{
return user.name.toLowerCase().includes(string_after_at);
});
this.setState({
[event.target.name]: value,
suggestions: new_suggestions,
});
} else {
this.setState({
[event.target.name]: value,
suggestions: [],
});
}
};
render = () => {
return (
<form onSubmit={this.handle_submit}>
<input
name="text"
value={this.state.text}
onChange={this.handle_input_change}/>
{this.state.suggestions.length > 0 &&
<Select
on_change={this.handle_select_value}
values={this.state.suggestions}/>}
</form>);
}
}
谢谢。
答案 0 :(得分:0)
查看是否适合您
function App() {
const inputRef = React.useRef(null);
const [inputValue, setInputValue] = React.useState('');
const [userList,setUserList] = React.useState([
{name: 'John Joe', username:'johnjoe'},
{name: 'Jane Jannet', username:'janejannet'},
{name: 'Jack Daniels', username:'jackdaniels'}
]
);
const [partialMention,setPartialMention] = React.useState(null);
const [showSuggestions,setShowSuggestions] = React.useState(false);
const [suggestionList,setSuggestionList] = React.useState(
['johnjoe','janejannet','jackdaniels']
);
function onChange(event) {
const regexp = /@[a-zA-Z0-9]*$/;
if (regexp.test(event.target.value)) {
setPartialMention(event.target.value.split('@').pop());
setShowSuggestions(true);
}
else {
setShowSuggestions(false);
}
setInputValue(event.target.value);
}
function focusInput() {
inputRef.current.focus();
}
return(
<React.Fragment>
<input ref={inputRef} type='text' value={inputValue} onChange={onChange}/>
{showSuggestions &&
<Suggestions
inputValue={inputValue}
suggestionList={suggestionList}
applyMention={onChange}
focusInput={focusInput}
partialMention={partialMention}
/>
}
</React.Fragment>
);
}
function Suggestions(props) {
function selectSuggestion(username) {
const regexp = /@[a-zA-Z0-9]*$/;
const newValue = props.inputValue.replace(regexp,username + ' ');
props.applyMention({target: {value: newValue}}); // THIS MIMICS AN ONCHANGE EVENT
props.focusInput();
}
const suggestionItems = props.suggestionList
.filter((item) => item.includes(props.partialMention))
.map((item) =>
<div className="item" onClick={()=>selectSuggestion('@' + item)}>@{item}</div>
);
return(
<div className="container">
{suggestionItems}
</div>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
.container {
border: 1px solid silver;
width: 150px;
}
.item {
cursor: pointer;
}
.item:hover {
color: blue;
}
input {
width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>