2021SC@SDUSC
Mentions提及
API
<Mentions onChange={onChange}> <Mentions.Option value="sample">Sample</Mentions.Option> </Mentions>
讯享网
属性:
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| autoFocus | 自动获得焦点 | boolean | false |
| autoSize | 自适应内容高度,可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 } | boolean | object | false |
| defaultValue | 默认值 | string | - |
| filterOption | 自定义过滤逻辑 | false | (input: string, option: OptionProps) => boolean | - |
| getPopupContainer | 指定建议框挂载的 HTML 节点 | () => HTMLElement | - |
| notFoundContent | 当下拉列表为空时显示的内容 | ReactNode | Not Found |
| placement | 弹出层展示位置 | top | bottom |
bottom |
| prefix | 设置触发关键字 | string | string[] | @ |
| split | 设置选中项前后分隔符 | string | |
| validateSearch | 自定义触发验证逻辑 | (text: string, props: MentionsProps) => void | - |
| value | 设置值 | string | - |
| onBlur | 失去焦点时触发 | () => void | - |
| onChange | 值改变时触发 | (text: string) => void | - |
| onFocus | 获得焦点时触发 | () => void | - |
| onResize | resize 回调 | function({ width, height }) | - |
| onSearch | 搜索时触发 | (text: string, prefix: string) => void | - |
| onSelect | 选择选项时触发 | (option: OptionProps, prefix: string) => void | - |
部分源码
讯享网import * as React from 'react'; import classNames from 'classnames'; import RcMentions from 'rc-mentions'; import {
MentionsProps as RcMentionsProps } from 'rc-mentions/lib/Mentions'; import {
composeRef } from 'rc-util/lib/ref'; import Spin from '../spin'; import {
ConfigContext } from '../config-provider'; export const {
Option } = RcMentions;
function loadingFilterOption() {
return true; }
启用自定义过滤逻辑
讯享网export type MentionPlacement = 'top' | 'bottom';
弹开层的展开位置
export interface OptionProps {
value: string; children: React.ReactNode; [key: string]: any; } export interface MentionProps extends RcMentionsProps {
loading?: boolean; } export interface MentionState {
focused: boolean; } interface MentionsConfig {
prefix?: string | string[]; split?: string; } interface MentionsEntity {
prefix: string; value: string; }
设置选项接口、选中状态、触发关键字、选中项前后分隔符、提及实体等接口
讯享网interface CompoundedComponent extends React.ForwardRefExoticComponent<MentionProps & React.RefAttributes<HTMLElement>> {
Option: typeof Option; getMentions: (value: string, config?: MentionsConfig) => MentionsEntity[]; }
此处运用到了ForwardRefExoticComponent
interface ExoticComponent<P = {
}> {
/ * NOTE: Exotic components are not callable. */ (props: P): (ReactElement|null); readonly $$typeof: symbol; } interface NamedExoticComponent<P = {
}> extends ExoticComponent<P> {
displayName?: string; } interface ForwardRefExoticComponent<P> extends NamedExoticComponent<P> {
defaultProps?: Partial<P>; propTypes?: WeakValidationMap<P>; }
与ForwardRefRenderFunction主要区别在于
ForwardRefRenderFunction不支持propType和defaultProps,而ForwardRefExoticComponent则支持ForwardRefExoticComponent有一个额外的typeof成员ForwardRefRenderFunction调用签名中有一个props对象,必需包含一个children成员以及一个ref对象作为参数,而ForwardRefExoticComponent的调用签名中只需要一个props对象的任意形式作为参数
讯享网interface ForwardRefRenderFunction<T, P = {
}> {
(props: PropsWithChildren<P>, ref: ((instance: T | null) => void) | MutableRefObject<T | null> | null): ReactElement | null; displayName?: string; defaultProps?: never; propTypes?: never; }
以上为ForwardRefRenderFunction作为参照
const InternalMentions: React.ForwardRefRenderFunction<unknown, MentionProps> = ( {
prefixCls: customizePrefixCls, className, disabled, loading, filterOption, children, notFoundContent, ...restProps }, ref, ) => {
const [focused, setFocused] = React.useState(false); const innerRef = React.useRef<HTMLElement>(); const mergedRef = composeRef(ref, innerRef); const {
getPrefixCls, renderEmpty, direction } = React.useContext(ConfigContext); const onFocus: React.FocusEventHandler<HTMLTextAreaElement> = (...args) => {
if (restProps.onFocus) {
restProps.onFocus(...args); } setFocused(true); }; const onBlur: React.FocusEventHandler<HTMLTextAreaElement> = (...args) => {
if (restProps.onBlur) {
restProps.onBlur(...args); } setFocused(false); }; const getNotFoundContent = () => {
if (notFoundContent !== undefined) {
return notFoundContent; } return renderEmpty('Select'); }; const getOptions = () => {
if (loading) {
return ( <Option value="ANTD_SEARCHING" disabled> <Spin size="small" /> </Option> ); } return children; }; const getFilterOption = (): any => {
if (loading) {
return loadingFilterOption; } return filterOption; }; const prefixCls = getPrefixCls('mentions', customizePrefixCls); const mergedClassName = classNames( {
[`${
prefixCls}-disabled`]: disabled, [`${
prefixCls}-focused`]: focused, [`${
prefixCls}-rtl`]: direction === 'rtl', }, className, ); return ( <RcMentions prefixCls={
prefixCls} notFoundContent={
getNotFoundContent()} className={
mergedClassName} disabled={
disabled} direction={
direction} {
...restProps} filterOption={
getFilterOption()} onFocus={
onFocus} onBlur={
onBlur} ref={
mergedRef as any} > {
getOptions()} </RcMentions> ); }; const Mentions = React.forwardRef<unknown, MentionProps>(InternalMentions) as CompoundedComponent; Mentions.displayName = 'Mentions'; Mentions.Option = Option; Mentions.getMentions = (value: string = '', config?: MentionsConfig): MentionsEntity[] => {
const {
prefix = '@', split = ' ' } = config || {
}; const prefixList: string[] = Array.isArray(prefix) ? prefix : [prefix]; return value .split(split) .map((str = ''): MentionsEntity | null => {
let hitPrefix: string | null = null; prefixList.some(prefixStr => {
const startStr = str.slice(0, prefixStr.length); if (startStr === prefixStr) {
hitPrefix = prefixStr; return true; } return false; }); if (hitPrefix !== null) {
return {
prefix: hitPrefix, value: str.slice((hitPrefix as string).length), }; } return null; }) .filter((entity): entity is MentionsEntity => !!entity && !!entity.value); }; export default Mentions;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/44630.html