botframework Webchat React 中的建议列表问题
对于您的第一个问题,可能有两种方法可以做到这一点。要以 React 方式执行此操作,您可以使用indexOf在建议中查找用户文本的索引,然后将文本拆分为多个 React 元素,其中一个以粗体显示。如果您想像replace目前一样使用,那么这可能是使用的好机会dangerouslySetInnerHTML:
<div className="SuggestionParent" id="Suggestion1">
{this.state.suggestions.map(suggestion => (
<div className="Suggestion" onClick={this.handleSuggestionClick} >
<div dangerouslySetInnerHTML={this.getSuggestionHtml(suggestion)} />
</div>
))}
</div>
“危险”警告是因为您需要确保不允许用户提供任何可以进入内部 HTML 的潜在值,否则他们可能会注入脚本标签。只要您的建议是从固定数据库中提取的并且数据是安全的,那么您可能没问题。否则,您将不得不清理 HTML,在这种情况下,根本不使用可能会更容易dangerouslySetInnerHTML。如果我们确实设置了内部 HTML,那么我们可以使用replace将 HTML 标签直接应用于字符串:
getSuggestionHtml(suggestion) {
const lowerCaseSuggestion = suggestion.toLowerCase();
return {
__html: lowerCaseSuggestion.includes(this.state.suggestionTypedText) ? lowerCaseSuggestion
.replace(this.state.suggestionTypedText, `<b>${this.state.suggestionTypedText}</b>`) : lowerCaseSuggestion
};
}
第二个问题,你说你已经解决了。我可以看到您正在使用布尔开关来暂时关闭您响应 WEB_CHAT/SET_SEND_BOX 操作的方式。
对于您的第三个问题,在确定您的 UI 将如何工作时,您必须问自己很多设计注意事项,例如“如果用户在使用箭头键时将鼠标悬停在建议上会发生什么? ” 和“在用户按下 Enter 键之前,是否应该在发送框中预览突出显示的建议?” 我希望找到一个预先存在的 React 自动完成组件,您可以使用它而不是构建自己的组件,因为这已经解决了所有这些潜在的陷阱。不幸的是,两个著名的 React 自动完成包(这里和这里)都有两个相同的问题:
- 他们目前没有得到维护
- 目标输入包含在组件中,因此您无法将组件连接到预先存在的输入。
但是,它们都是开源的,因此我们可以在它们之后为我们自己的自动完成功能建模。我将指导您完成基本功能,您可以根据需要进行扩展。
键盘事件通常在 React 中使用onKeyDown属性处理。我把它放在一个包含网络聊天和你的建议父元素的元素上:
<div className={ROOT_CSS} onKeyDown={this.handleKeyDown.bind(this)}>
<div className={WEB_CHAT_CSS + ''}>
<ReactWebChat
这将处理所有按键操作,因此您需要一种方法来路由到正确键的功能。您可以使用switch语句,但react-autocomplete的源代码使用查找对象,我认为这很聪明。
keyDownHandlers = {
ArrowDown(event) {
this.moveHighlight(event, 1);
},
ArrowUp(event) {
this.moveHighlight(event, -1);
},
Enter(event) {
const {suggestions} = this.state;
if (!suggestions.length) {
// menu is closed so there is no selection to accept -> do nothing
return
}
event.preventDefault()
this.applySuggestion(suggestions[this.state.highlightedIndex]);
},
}
handleKeyDown(event) {
if (this.keyDownHandlers[event.key])
this.keyDownHandlers[event.key].call(this, event)
}
我已将向上和向下箭头的功能集中到一个功能中:moveHighlight. 您将需要在您的状态中定义一个新属性,以跟踪键盘选择了哪个建议。我保留了highlightedIndexreact自动完成的名称。
moveHighlight(event, direction) {
event.preventDefault();
const { highlightedIndex, suggestions } = this.state;
if (!suggestions.length) return;
let newIndex = (highlightedIndex + direction + suggestions.length) % suggestions.length;
if (newIndex !== highlightedIndex) {
this.setState({
highlightedIndex: newIndex,
});
}
}
对于应用建议的回车键,您需要集中您的功能,以便它的工作方式与鼠标单击相同。
async handleSuggestionClick(event) {
await this.applySuggestion(event.currentTarget.textContent);
}
async applySuggestion(newValue) {
await this.setState({ typingChecking: "false", suggestions: [], highlightedIndex: 0 });
this.state.suggestionCallback.dispatch({
type: 'WEB_CHAT/SET_SEND_BOX',
payload: {
text: newValue,
}
});
await this.setState({ typingChecking: "true" });
}
最后,确保该highlightedIndex属性用于以不同方式呈现突出显示的索引。
getSuggestionCss(index) {
return index === this.state.highlightedIndex ? HIGHLIGHTED_CSS : SUGGESTION_CSS;
}
. . .
<div className="SuggestionParent" id="Suggestion1">
{this.state.suggestions.map((suggestion, index) => (
<div className={this.getSuggestionCss(index)} key={index} onClick={this.handleSuggestionClick} >
<div dangerouslySetInnerHTML={this.getSuggestionHtml(suggestion)} />
</div>
))}
</div>

