Mention提及

提及组件。

何时使用

用于在输入中提及某人或某事,常用于发布、聊天或评论功能。

代码演示

Mention 提及 - 图1

基本使用

基本使用

  1. import { Mention } from 'antd';
  2. const { toString, toContentState } = Mention;
  3. function onChange(contentState) {
  4. console.log(toString(contentState));
  5. }
  6. function onSelect(suggestion) {
  7. console.log('onSelect', suggestion);
  8. }
  9. ReactDOM.render(
  10. <Mention
  11. style={{ width: '100%' }}
  12. onChange={onChange}
  13. defaultValue={toContentState('@afc163')}
  14. defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
  15. onSelect={onSelect}
  16. />,
  17. mountNode,
  18. );

Mention 提及 - 图2

异步加载

匹配内容列表为异步返回时。

  1. import { Mention } from 'antd';
  2. const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
  3. class AsyncMention extends React.Component {
  4. state = {
  5. suggestions: [],
  6. loading: false,
  7. };
  8. fetchSuggestions = (value, callback) => {
  9. setTimeout(() => {
  10. callback(users.filter(item => item.indexOf(value) !== -1));
  11. }, 500);
  12. };
  13. onSearchChange = value => {
  14. this.fetchSuggestions(value, suggestions => {
  15. this.setState({
  16. suggestions,
  17. loading: false,
  18. });
  19. });
  20. this.setState({
  21. loading: true,
  22. });
  23. };
  24. render() {
  25. const { suggestions, loading } = this.state;
  26. return (
  27. <Mention
  28. style={{ width: '100%' }}
  29. loading={loading}
  30. suggestions={suggestions}
  31. onSearchChange={this.onSearchChange}
  32. />
  33. );
  34. }
  35. }
  36. ReactDOM.render(<AsyncMention />, mountNode);

Mention 提及 - 图3

头像

自定义建议(含头像)

注意,自定义建议时,onSearchChange 必须不能为空。

  1. import { Mention, Avatar } from 'antd';
  2. const Nav = Mention.Nav;
  3. const webFrameworks = [
  4. {
  5. name: 'React',
  6. type: 'JavaScript',
  7. icon: 'https://zos.alipayobjects.com/rmsportal/LFIeMPzdLcLnEUe.svg',
  8. },
  9. {
  10. name: 'Angular',
  11. type: 'JavaScript',
  12. icon: 'https://zos.alipayobjects.com/rmsportal/PJTbxSvzYWjDZnJ.png',
  13. },
  14. {
  15. name: 'Dva',
  16. type: 'Javascript',
  17. icon: 'https://zos.alipayobjects.com/rmsportal/EYPwSeEJKxDtVxI.png',
  18. },
  19. {
  20. name: 'Flask',
  21. type: 'Python',
  22. icon: 'https://zos.alipayobjects.com/rmsportal/xaypBUijfnpAlXE.png',
  23. },
  24. ];
  25. class CustomNavMention extends React.Component {
  26. state = {
  27. suggestions: [],
  28. };
  29. onSearchChange = value => {
  30. const searchValue = value.toLowerCase();
  31. const filtered = webFrameworks.filter(
  32. item => item.name.toLowerCase().indexOf(searchValue) !== -1,
  33. );
  34. const suggestions = filtered.map(suggestion => (
  35. <Nav value={suggestion.name} data={suggestion} disabled={suggestion.disabled}>
  36. <Avatar
  37. src={suggestion.icon}
  38. size="small"
  39. style={{
  40. width: 14,
  41. height: 14,
  42. marginRight: 8,
  43. top: -1,
  44. position: 'relative',
  45. }}
  46. />
  47. {suggestion.name} - {suggestion.type}
  48. </Nav>
  49. ));
  50. this.setState({ suggestions });
  51. };
  52. render() {
  53. const { suggestions } = this.state;
  54. return (
  55. <Mention
  56. style={{ width: '100%' }}
  57. suggestions={suggestions}
  58. onSearchChange={this.onSearchChange}
  59. />
  60. );
  61. }
  62. }
  63. ReactDOM.render(<CustomNavMention />, mountNode);

Mention 提及 - 图4

配合 Form 使用

受控模式,例如配合 Form 使用。

  1. import { Mention, Form, Button } from 'antd';
  2. const { toContentState, getMentions } = Mention;
  3. const FormItem = Form.Item;
  4. class App extends React.Component {
  5. state = {
  6. initValue: toContentState('@afc163'),
  7. };
  8. handleReset = e => {
  9. e.preventDefault();
  10. this.props.form.resetFields();
  11. };
  12. handleSubmit = e => {
  13. e.preventDefault();
  14. this.props.form.validateFields((errors, values) => {
  15. if (errors) {
  16. console.log('Errors in the form!!!');
  17. return;
  18. }
  19. console.log('Submit!!!');
  20. console.log(values);
  21. });
  22. };
  23. checkMention = (rule, value, callback) => {
  24. const { getFieldValue } = this.props.form;
  25. const mentions = getMentions(getFieldValue('mention'));
  26. if (mentions.length < 2) {
  27. callback(new Error('More than one must be selected!'));
  28. } else {
  29. callback();
  30. }
  31. };
  32. render() {
  33. const { getFieldDecorator, getFieldValue } = this.props.form;
  34. console.log('>> render', getFieldValue('mention') === this.state.initValue);
  35. return (
  36. <Form layout="horizontal">
  37. <FormItem
  38. id="control-mention"
  39. label="Top coders"
  40. labelCol={{ span: 6 }}
  41. wrapperCol={{ span: 16 }}
  42. >
  43. {getFieldDecorator('mention', {
  44. rules: [{ validator: this.checkMention }],
  45. initialValue: this.state.initValue,
  46. })(
  47. <Mention
  48. defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
  49. />,
  50. )}
  51. </FormItem>
  52. <FormItem wrapperCol={{ span: 14, offset: 6 }}>
  53. <Button type="primary" onClick={this.handleSubmit}>
  54. Submit
  55. </Button>
  56. &nbsp;&nbsp;&nbsp;
  57. <Button onClick={this.handleReset}>Reset</Button>
  58. </FormItem>
  59. </Form>
  60. );
  61. }
  62. }
  63. const FormDemo = Form.create()(App);
  64. ReactDOM.render(<FormDemo />, mountNode);

Mention 提及 - 图5

建议渲染父节点

指定提示渲染的父节点。

  1. import { Mention, Popover, Button } from 'antd';
  2. const { toString, toContentState } = Mention;
  3. function onChange(editorState) {
  4. console.log(toString(editorState));
  5. }
  6. function onSelect(suggestion) {
  7. console.log('onSelect', suggestion);
  8. }
  9. class PopoverContainer extends React.Component {
  10. getSuggestionContainer = () => this.popover.getPopupDomNode();
  11. visibleChange = visible => {
  12. if (visible && this.mention) {
  13. this.mention.focus();
  14. }
  15. };
  16. render() {
  17. const mention = (
  18. <Mention
  19. ref={ele => (this.mention = ele)}
  20. style={{ width: '100%' }}
  21. onChange={onChange}
  22. defaultValue={toContentState('@afc163')}
  23. defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
  24. onSelect={onSelect}
  25. getSuggestionContainer={this.getSuggestionContainer}
  26. />
  27. );
  28. return (
  29. <Popover
  30. trigger="click"
  31. content={mention}
  32. title="Title"
  33. ref={popover => (this.popover = popover)}
  34. onVisibleChange={this.visibleChange}
  35. >
  36. <Button type="primary">Click Me</Button>
  37. </Popover>
  38. );
  39. }
  40. }
  41. ReactDOM.render(<PopoverContainer />, mountNode);

Mention 提及 - 图6

自定义触发字符

通过 prefix 属性自定义触发字符。默认为 @, 可以定义为数组。

  1. import { Mention } from 'antd';
  2. const { toString } = Mention;
  3. function onChange(editorState) {
  4. console.log(toString(editorState));
  5. }
  6. function onSelect(suggestion) {
  7. console.log('onSelect', suggestion);
  8. }
  9. const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
  10. const tags = ['1.0', '2.0', '3.0'];
  11. class App extends React.Component {
  12. constructor() {
  13. super();
  14. this.state = {
  15. suggestions: [],
  16. };
  17. }
  18. onSearchChange = (value, trigger) => {
  19. console.log('onSearchChange', value, trigger);
  20. const dataSource = trigger === '@' ? users : tags;
  21. this.setState({
  22. suggestions: dataSource.filter(item => item.indexOf(value) !== -1),
  23. });
  24. };
  25. render() {
  26. return (
  27. <Mention
  28. style={{ width: '100%' }}
  29. onChange={onChange}
  30. placeholder="input @ to mention people, # to mention tag"
  31. prefix={['@', '#']}
  32. onSearchChange={this.onSearchChange}
  33. suggestions={this.state.suggestions}
  34. onSelect={onSelect}
  35. />
  36. );
  37. }
  38. }
  39. ReactDOM.render(<App />, mountNode);

Mention 提及 - 图7

向上展开

向上展开建议。

  1. import { Mention } from 'antd';
  2. const { toString } = Mention;
  3. function onChange(contentState) {
  4. console.log(toString(contentState));
  5. }
  6. function onSelect(suggestion) {
  7. console.log('onSelect', suggestion);
  8. }
  9. ReactDOM.render(
  10. <Mention
  11. style={{ width: '100%' }}
  12. onChange={onChange}
  13. defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
  14. onSelect={onSelect}
  15. placement="top"
  16. />,
  17. mountNode,
  18. );

Mention 提及 - 图8

自定义建议

自定义建议

注意,自定义建议时,onSearchChange 必须不能为空。

  1. import { Mention } from 'antd';
  2. const Nav = Mention.Nav;
  3. const webFrameworks = [
  4. { name: 'React', type: 'JavaScript' },
  5. { name: 'Angular', type: 'JavaScript' },
  6. { name: 'Laravel', type: 'PHP', disabled: true },
  7. { name: 'Flask', type: 'Python' },
  8. { name: 'Django', type: 'Python' },
  9. ];
  10. function onSelect(suggestion, data) {
  11. console.log('onSelect', suggestion, data);
  12. }
  13. class CustomNavMention extends React.Component {
  14. state = {
  15. suggestions: [],
  16. };
  17. onSearchChange = value => {
  18. const searchValue = value.toLowerCase();
  19. const filtered = webFrameworks.filter(
  20. item => item.name.toLowerCase().indexOf(searchValue) !== -1,
  21. );
  22. const suggestions = filtered.map(suggestion => (
  23. <Nav value={suggestion.name} data={suggestion}>
  24. <span>
  25. {suggestion.name} - {suggestion.type}
  26. </span>
  27. </Nav>
  28. ));
  29. this.setState({ suggestions });
  30. };
  31. render() {
  32. const { suggestions } = this.state;
  33. return (
  34. <Mention
  35. placeholder="@someone"
  36. style={{ width: '100%' }}
  37. suggestions={suggestions}
  38. onSearchChange={this.onSearchChange}
  39. onSelect={onSelect}
  40. />
  41. );
  42. }
  43. }
  44. ReactDOM.render(<CustomNavMention />, mountNode);

Mention 提及 - 图9

受控模式

受控模式.

  1. import { Mention } from 'antd';
  2. const { toContentState } = Mention;
  3. class App extends React.Component {
  4. state = {
  5. value: toContentState('@afc163'),
  6. };
  7. componentDidMount() {
  8. this.mention.focus();
  9. }
  10. handleChange = editorState => {
  11. this.setState({
  12. value: editorState,
  13. });
  14. };
  15. render() {
  16. return (
  17. <Mention
  18. ref={ele => (this.mention = ele)}
  19. defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
  20. value={this.state.value}
  21. onChange={this.handleChange}
  22. />
  23. );
  24. }
  25. }
  26. ReactDOM.render(<App />, mountNode);

Mention 提及 - 图10

多行

多行模式,多行模式必须指定高度。

  1. import { Mention } from 'antd';
  2. const { toString } = Mention;
  3. function onChange(editorState) {
  4. console.log(toString(editorState));
  5. }
  6. ReactDOM.render(
  7. <Mention
  8. style={{ width: '100%', height: 100 }}
  9. onChange={onChange}
  10. defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai']}
  11. multiLines
  12. />,
  13. mountNode,
  14. );

Mention 提及 - 图11

无效或只读

通过 disabled 属性设置是否生效。通过 readOnly 属性设置是否只读。

  1. import { Mention } from 'antd';
  2. const { toString } = Mention;
  3. function onChange(editorState) {
  4. console.log(toString(editorState));
  5. }
  6. const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
  7. function App() {
  8. return (
  9. <div>
  10. <div style={{ marginBottom: 10 }}>
  11. <Mention
  12. style={{ width: '100%' }}
  13. onChange={onChange}
  14. placeholder="this is disabled Mention"
  15. suggestions={users}
  16. disabled
  17. />
  18. </div>
  19. <Mention
  20. style={{ width: '100%' }}
  21. onChange={onChange}
  22. placeholder="this is readOnly Mention"
  23. suggestions={users}
  24. readOnly
  25. />
  26. </div>
  27. );
  28. }
  29. ReactDOM.render(<App />, mountNode);

API

  1. <Mention
  2. onChange={onChange}
  3. suggestions={['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai']}
  4. />

Mention API

API说明类型
getMentions获取当前 contentState 中提到的人的列表Function(contentState: ContentState): string[]
toContentState把字符串转成 ContentStateFunction(value: string): ContentState
toString把 ContentState 转成字符串Function(contentState: ContentState): string

Mention

参数说明类型默认值
autoFocus自动获取焦点booleanfalse
defaultValue默认值ContentState, 可以用 Mention.toContentState(text) 把文字转换成 ContentStatenull
defaultSuggestions默认建议内容Array<string|Mention.Nav>[]
disabled是否禁用状态.booleanfalse
getSuggestionContainer菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位function()() => document.body
loading加载中booleanfalse
multiLines多行模式booleanfalse
notFoundContent未找到时的内容string'无匹配结果,轻敲空格完成输入'
placeholder输入框默认文字stringnull
placement建议框位置,可选 top bottomstring'bottom'
prefix触发弹出下拉框的字符string or Array<string>'@'
readOnly是否只读.booleanfalse
suggestions建议内容Array<string|Mention.Nav>[]
suggestionStyle弹出下拉框样式object{}
valueContentStatenull
onBlur失去焦点时回调function(e)null
onChange输入框内容变化时回调function(contentState: ContentState)null
onFocus获得焦点时回调function(e)null
onSearchChange输入框中 @ 变化时回调function(value:string, trigger: string)[]
onSelect下拉框选择建议时回调function(suggestion: string, data?: any)null

Mention 方法

名称描述
blur()移除焦点
focus()获取焦点

Nav

参数说明类型默认值
children建议内容object{}
value建议值,选择建议时,用此值插入到输入框中string""