Mention提及(废弃)

提及组件。已废弃,请使用 Mentions 代替。

为何废弃?

Mention 组件使用了Draft.js进行提示定位,占用了约 11.6% 的包大小。因而我们决定使用更轻量级的解决方案以便于在未来降低整个包的大小。

代码演示

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;
  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;
  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""