@功能
会话是群组时,输入框提供@功能,用户是当前群的群主时,suggestionsList包含
@全体成员
;@组件使用Draft plugins提供的mention plugin
主要code:
import Editor from 'draft-js-plugins-editor';
import createMentionPlugin, {defaultSuggestionsFilter} from 'draft-js-mention-plugin';
import createLinkifyPlugin from 'draft-js-linkify-plugin';
import 'draft-js-mention-plugin/lib/plugin.css';
import 'draft-js-linkify-plugin/lib/plugin.css';
import MentionEntry from './Mention';
// 自定义mention弹出的位置
const positionSuggestions = ({decoratorRect, state, props}) => {
const editorWrapper = document.getElementsByClassName('chat-draft-editor')[0];
const wrapperRect = editorWrapper.getBoundingClientRect();
let left = decoratorRect.left - wrapperRect.left;
const newDecoratorRight = decoratorRect.left + 170;
if (newDecoratorRight >= wrapperRect.right) {
left = left - (newDecoratorRight - wrapperRect.right) - 10;
}
const bottom = wrapperRect.height + 25 - (decoratorRect.bottom - wrapperRect.top);
console.log('editor', decoratorRect);
let transform;
let transition;
if (state.isActive & props.suggestions.size > 0) {
transform = 'scale(1)';
transition = 'all 0.25s cubic-bezier(.3,1.2,.2,1)';
} else if (state.isActive) {
transform = 'scale(0)';
transition = 'all 0.35s cubic-bezier(.3,1,.2,1)';
}
return {
position: 'absolute',
left: `${left}px`,
bottom: `${bottom}px`,
minWidth: '170px',
maxHeight: '230px',
overflowY: 'scroll',
border: '1px solid #E6E6E6',
borderRadius: '6px',
transform,
transformOrigin: '1em 0%',
transition,
};
};
const defaultSuggestions = [];
export default class ChatDraftEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty(),
suggestions: [],
};
this.mentionPlugin = createMentionPlugin({
defaultSuggestions,
entityMutability: 'IMMUTABLE',
positionSuggestions,
mentionPrefix: '@',
});
}
}
onSearchChange = ({value}) => {
const userList = this.props.userList;
const filterSuggestions = value === ''? userList : defaultSuggestionsFilter(value, userList);
this.setState({
suggestions: filterSuggestions,
});
};
render() {
const {MentionSuggestions} = this.mentionPlugin;
const plugins = [this.mentionPlugin];
return (
<div
className="chat-draft-editor"
onClick={()=> {
this.focus(0);
}}
>
<Editor
ref={(e) => {
this.editor = e;
}}
plugins={plugins}
decorators={draftDecorator}
editorState={this.state.editorState}
onChange={this.onChange.bind(this)}
onBlur={this.handleBlur.bind(this)}
blockRendererFn={this.blockRendererFn.bind(this)}
handleKeyCommand={this.handleKeyCommand.bind(this)}
keyBindingFn={this.keyBindingFn}
/>
<MentionSuggestions
onSearchChange={this.onSearchChange.bind(this)}
suggestions={this.state.suggestions}
entryComponent={MentionEntry}
// onOpen={this.handleMentionOpen.bind(this)}
// onClose={this.handleMentionClose.bind(this)}
/>
</div>
);
}
-
<MetionSuggestions />
是@列表组件,其属性suggestions
为数组对象,格式可以自定义..如果格式自定义了的话,最好同时修改entryComponent
-
entryComponent
用来传入自定义的mention列表中item的组件样式,意味着可以根据你的mention对象格式定制组件样式:import React from 'react'; import Avatar from '../common/Avatar'; const MentionEntry = (props) => { const { mention, ...parentProps } = props; const isAll = mention.get('uid') == 'upcgroupatall' ? true: false; const avatarType = mention.get('gender') == '2'? 'women': 'men'; const suggestionEntry = isAll? ( <div className="mention-all">{mention.get('name')}</div> ): ( <div className="mention-entry"> <Avatar icon={mention.get('avatar')} shape="square" size="min" type={avatarType} /> <div className="mention-text">{mention.get('name')}</div> </div> ); return ( <div {...parentProps}> <div className="mention-suggestion" > {suggestionEntry} </div> </div> ); }; module.exports = MentionEntry;
-
onSearchChange
绑定@时的关键字filter方法:onSearchChange = ({value}) => { const userList = this.props.userList; const filterSuggestions = value === ''? userList : defaultSuggestionsFilter(value, userList); this.setState({ suggestions: filterSuggestions, }); };
这里原本按照官网demo写,会导致一个bug,即第一次触发@,value为''时,filter方法并未返回整个list。因此添加判断如上。
-
mention插件目前仍有些未解决的影响体验的问题:会影响输入框up/down arrow事件的正常处理;mention选择时,滚轮不会随着up/down arrow滚动
网友评论