Mentions提及

提及组件。

何时使用#

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

代码演示

基本使用。

expand codeexpand code
import { Mentions } from 'infrad';
import type { OptionProps } from 'infrad/es/mentions';
import React from 'react';

const { Option } = Mentions;

const onChange = (value: string) => {
  console.log('Change:', value);
};

const onSelect = (option: OptionProps) => {
  console.log('select', option);
};

const App: React.FC = () => (
  <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>
);

export default App;
   

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

expand codeexpand code
import { Button, Form, Mentions } from 'infrad';
import React from 'react';

const { Option, getMentions } = Mentions;

const App: React.FC = () => {
  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 (_: any, value: string) => {
    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>
  );
};

export default App;

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

expand codeexpand code
import { Mentions } from 'infrad';
import React from 'react';

const { Option } = Mentions;

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

const App: React.FC = () => (
  <>
    <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>
  </>
);

export default App;

自适应内容高度。

expand codeexpand code
import { Mentions } from 'infrad';
import React from 'react';

const { Option } = Mentions;

const App: React.FC = () => (
  <Mentions autoSize style={{ width: '100%' }}>
    <Option value="afc163">afc163</Option>
    <Option value="zombieJ">zombieJ</Option>
    <Option value="yesmeck">yesmeck</Option>
  </Mentions>
);

export default App;

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

expand codeexpand code
import { Mentions } from 'infrad';
import debounce from 'lodash/debounce';
import React, { useCallback, useRef, useState } from 'react';

const { Option } = Mentions;
const App: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [users, setUsers] = useState<{ login: string; avatar_url: string }[]>([]);
  const ref = useRef<string>();

  const loadGithubUsers = (key: string) => {
    if (!key) {
      setUsers([]);
      return;
    }

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

        setLoading(false);
        setUsers(items.slice(0, 10));
      });
  };

  const debounceLoadGithubUsers = useCallback(debounce(loadGithubUsers, 800), []);

  const onSearch = (search: string) => {
    console.log('Search:', search);
    ref.current = search;
    setLoading(!!search);
    setUsers([]);

    debounceLoadGithubUsers(search);
  };

  return (
    <Mentions style={{ width: '100%' }} loading={loading} onSearch={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>
  );
};

export default App;

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

expand codeexpand code
import { Mentions } from 'infrad';
import React, { useState } from 'react';

const { Option } = Mentions;

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

type PrefixType = keyof typeof MOCK_DATA;

const App: React.FC = () => {
  const [prefix, setPrefix] = useState<PrefixType>('@');

  const onSearch = (_: string, newPrefix: PrefixType) => {
    setPrefix(newPrefix);
  };

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

export default App;

向上展开建议。

expand codeexpand code
import { Mentions } from 'infrad';
import React from 'react';

const { Option } = Mentions;

const App: React.FC = () => (
  <Mentions style={{ width: '100%' }} placement="top">
    <Option value="afc163">afc163</Option>
    <Option value="zombieJ">zombieJ</Option>
    <Option value="yesmeck">yesmeck</Option>
  </Mentions>
);

export default App;

使用 status 为 Mentions 添加状态。可选 error 或者 warning

expand codeexpand code
import { Mentions, Space } from 'infrad';
import type { OptionProps } from 'infrad/es/mentions';
import React from 'react';

const { Option } = Mentions;

const onChange = (value: string) => {
  console.log('Change:', value);
};

const onSelect = (option: OptionProps) => {
  console.log('select', option);
};

const App: React.FC = () => {
  const options = (
    <>
      <Option value="afc163">afc163</Option>
      <Option value="zombieJ">zombieJ</Option>
      <Option value="yesmeck">yesmeck</Option>
    </>
  );

  return (
    <Space direction="vertical">
      <Mentions onChange={onChange} onSelect={onSelect} defaultValue="@afc163" status="error">
        {options}
      </Mentions>
      <Mentions onChange={onChange} onSelect={onSelect} defaultValue="@afc163" status="warning">
        {options}
      </Mentions>
    </Space>
  );
};

export default App;

API#

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

Mentions#

参数说明类型默认值版本
autoFocus自动获得焦点booleanfalse
autoSize自适应内容高度,可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 }boolean | objectfalse
defaultValue默认值string-
filterOption自定义过滤逻辑false | (input: string, option: OptionProps) => boolean-
getPopupContainer指定建议框挂载的 HTML 节点() => HTMLElement-
notFoundContent当下拉列表为空时显示的内容ReactNodeNot Found
placement弹出层展示位置top | bottombottom
prefix设置触发关键字string | string[]@
split设置选中项前后分隔符string
status设置校验状态'error' | 'warning'-4.19.0
validateSearch自定义触发验证逻辑(text: string, props: MentionsProps) => void-
value设置值string-
onBlur失去焦点时触发() => void-
onChange值改变时触发(text: string) => void-
onFocus获得焦点时触发() => void-
onResizeresize 回调function({ width, height })-
onSearch搜索时触发(text: string, prefix: string) => void-
onSelect选择选项时触发(option: OptionProps, prefix: string) => void-

Mentions 方法#

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

Option#

参数说明类型默认值
children选项内容ReactNode-
value选择时填充的值string-