Mentions提及

提及组件。

何时使用#

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

代码演示

基本使用

expand codeexpand code
import { Mentions } from 'antd';

const { Option } = Mentions;

function onChange(value) {
  console.log('Change:', value);
}

function onSelect(option) {
  console.log('select', option);
}

ReactDOM.render(
  <Mentions
    style={{ width: '100%' }}
    onChange={onChange}
    onSelect={onSelect}
    defaultValue="@afc163"
  >
    <Option value="afc163">afc163</Option>
    <Option value="zombieJ">zombieJ</Option>
    <Option value="yesmeck">yesmeck</Option>
  </Mentions>,
  mountNode,
);
   

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

expand codeexpand code
import { Mentions, Form, Button } from 'antd';

const { Option, getMentions } = Mentions;

const App = () => {
  const [form] = Form.useForm();

  const onReset = () => {
    form.resetFields();
  };

  const onFinish = async () => {
    try {
      const values = await form.validateFields();
      console.log('Submit:', values);
    } catch (errInfo) {
      console.log('Error:', errInfo);
    }
  };

  const checkMention = async (rule, value, callback) => {
    const mentions = getMentions(value);

    if (mentions.length < 2) {
      throw new Error('More than one must be selected!');
    }
  };

  return (
    <Form form={form} layout="horizontal" onFinish={onFinish}>
      <Form.Item
        name="coders"
        label="Top coders"
        labelCol={{ span: 6 }}
        wrapperCol={{ span: 16 }}
        rules={[{ validator: checkMention }]}
      >
        <Mentions rows="1">
          <Option value="afc163">afc163</Option>
          <Option value="zombieJ">zombieJ</Option>
          <Option value="yesmeck">yesmeck</Option>
        </Mentions>
      </Form.Item>
      <Form.Item
        name="bio"
        label="Bio"
        labelCol={{ span: 6 }}
        wrapperCol={{ span: 16 }}
        rules={[{ required: true }]}
      >
        <Mentions rows="3" placeholder="You can use @ to ref user here">
          <Option value="afc163">afc163</Option>
          <Option value="zombieJ">zombieJ</Option>
          <Option value="yesmeck">yesmeck</Option>
        </Mentions>
      </Form.Item>
      <Form.Item wrapperCol={{ span: 14, offset: 6 }}>
        <Button htmlType="submit" type="primary">
          Submit
        </Button>
        &nbsp;&nbsp;&nbsp;
        <Button htmlType="button" onClick={onReset}>
          Reset
        </Button>
      </Form.Item>
    </Form>
  );
};

ReactDOM.render(<App />, mountNode);

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

expand codeexpand code
import { Mentions } from 'antd';

const { Option } = Mentions;

function getOptions() {
  return ['afc163', 'zombiej', 'yesmeck'].map(value => (
    <Option key={value} value={value}>
      {value}
    </Option>
  ));
}

function App() {
  return (
    <div>
      <div style={{ marginBottom: 10 }}>
        <Mentions style={{ width: '100%' }} placeholder="this is disabled Mentions" disabled>
          {getOptions()}
        </Mentions>
      </div>
      <Mentions style={{ width: '100%' }} placeholder="this is readOnly Mentions" readOnly>
        {getOptions()}
      </Mentions>
    </div>
  );
}

ReactDOM.render(<App />, mountNode);

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

expand codeexpand code
import { Mentions } from 'antd';
import debounce from 'lodash/debounce';

const { Option } = Mentions;

class AsyncMention extends React.Component {
  constructor() {
    super();

    this.loadGithubUsers = debounce(this.loadGithubUsers, 800);
  }

  state = {
    search: '',
    loading: false,
    users: [],
  };

  onSearch = search => {
    this.setState({ search, loading: !!search, users: [] });
    console.log('Search:', search);
    this.loadGithubUsers(search);
  };

  loadGithubUsers(key) {
    if (!key) {
      this.setState({
        users: [],
      });
      return;
    }

    fetch(`https://api.github.com/search/users?q=${key}`)
      .then(res => res.json())
      .then(({ items = [] }) => {
        const { search } = this.state;
        if (search !== key) return;

        this.setState({
          users: items.slice(0, 10),
          loading: false,
        });
      });
  }

  render() {
    const { users, loading } = this.state;

    return (
      <Mentions style={{ width: '100%' }} loading={loading} onSearch={this.onSearch}>
        {users.map(({ login, avatar_url: avatar }) => (
          <Option key={login} value={login} className="antd-demo-dynamic-option">
            <img src={avatar} alt={login} />
            <span>{login}</span>
          </Option>
        ))}
      </Mentions>
    );
  }
}

ReactDOM.render(<AsyncMention />, mountNode);

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

expand codeexpand code
import { Mentions } from 'antd';

const { Option } = Mentions;

const MOCK_DATA = {
  '@': ['afc163', 'zombiej', 'yesmeck'],
  '#': ['1.0', '2.0', '3.0'],
};

class App extends React.Component {
  state = {
    prefix: '@',
  };

  onSearch = (_, prefix) => {
    this.setState({ prefix });
  };

  render() {
    const { prefix } = this.state;

    return (
      <Mentions
        style={{ width: '100%' }}
        placeholder="input @ to mention people, # to mention tag"
        prefix={['@', '#']}
        onSearch={this.onSearch}
      >
        {(MOCK_DATA[prefix] || []).map(value => (
          <Option key={value} value={value}>
            {value}
          </Option>
        ))}
      </Mentions>
    );
  }
}

ReactDOM.render(<App />, mountNode);

向上展开建议。

expand codeexpand code
import { Mentions } from 'antd';

const { Option } = Mentions;

ReactDOM.render(
  <Mentions style={{ width: '100%' }} placement="top">
    <Option value="afc163">afc163</Option>
    <Option value="zombieJ">zombieJ</Option>
    <Option value="yesmeck">yesmeck</Option>
  </Mentions>,
  mountNode,
);

API#

<Mentions onChange={onChange}>
  <Mentions.Option value="sample">Sample</Mentions.Option>
</Mentions>

Mentions#

参数说明类型默认值
autoFocus自动获得焦点booleanfalse
defaultValue默认值string
filterOption自定义过滤逻辑false | (input: string, option: OptionProps) => boolean
notFoundContent当下拉列表为空时显示的内容ReactNode'Not Found'
placement弹出层展示位置top | bottombottom
prefix设置触发关键字string | string[]'@'
split设置选中项前后分隔符string' '
validateSearch自定义触发验证逻辑(text: string, props: MentionsProps) => void
value设置值string
onChange值改变时触发(text: string) => void
onSelect选择选项时触发(option: OptionProps, prefix: string) => void
onSearch搜索时触发(text: string, prefix: string) => void
onFocus获得焦点时触发() => void
onBlur失去焦点时触发() => void
getPopupContainer指定建议框挂载的 HTML 节点() => HTMLElement

Mentions 方法#

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

Option#

参数说明类型默认值
children选项内容ReactNode
value选择时填充的值string''
Input输入框Rate评分