Mention提及

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

    基本使用

    基本使用

    Mention 提及 - 图2

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

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

    头像

    自定义建议(含头像)

    注意,自定义建议时,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);

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

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

    Mention 提及 - 图5

    建议渲染父节点

    指定提示渲染的父节点。

    通过 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. function onSelect(suggestion) {
    6. console.log('onSelect', suggestion);
    7. ReactDOM.render(
    8. <Mention
    9. style={{ width: '100%' }}
    10. onChange={onChange}
    11. defaultSuggestions={['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご']}
    12. onSelect={onSelect}
    13. placement="top"
    14. />,
    15. mountNode,
    16. );

    自定义建议

    注意,自定义建议时,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 提及 - 图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. );

    无效或只读

    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);
    1. <Mention
    2. onChange={onChange}
    3. suggestions={['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai']}
    4. />