链接在node_modules/next/dist/client/link.d.ts中定义如下
/// <reference types="node" />
import React from 'react';
import { UrlObject } from 'url';
declare type Url = string | UrlObject;
export declare type LinkProps = {
href: Url;
as?: Url;
replace?: boolean;
scroll?: boolean;
shallow?: boolean;
passHref?: boolean;
prefetch?: boolean;
locale?: string | false;
};
declare function Link(props: React.PropsWithChildren<LinkProps>): React.DetailedReactHTMLElement<{
onMouseEnter?: ((event: React.MouseEvent<Element, MouseEvent>) => void) | undefined;
onClick: (event: React.MouseEvent<Element, MouseEvent>) => void;
href?: string | undefined;
ref?: any;
}, HTMLElement>;
export default Link;
您必须导入 LinkProps 或自己定义该类型
属性href 的类型为Url,其定义为
declare type Url = string | UrlObject
UrlObject 定义为
interface UrlObject {
auth?: string | null;
hash?: string | null;
host?: string | null;
hostname?: string | null;
href?: string | null;
pathname?: string | null;
protocol?: string | null;
search?: string | null;
slashes?: boolean | null;
port?: string | number | null;
query?: string | null | ParsedUrlQueryInput;
}
ParsedUrlQueryInput 在哪里
interface ParsedUrlQueryInput extends NodeJS.Dict<string | number | boolean | ReadonlyArray<string> | ReadonlyArray<number> | ReadonlyArray<boolean> | null> {}
这是interface ParsedUrlQuery 的输入值,接下来使用 router.query/context.query 或 context.params(在 getStaticProps 中)获得。 ParsedUrlQuery 是字典类型:
interface ParsedUrlQuery extends NodeJS.Dict<string | string[]> { }
唯一可行的方法是如果您获得LinkProps 或自己定义它们,那么您必须使用React.forwardRef 并合并注入Links 属性的自定义组件的引用...或者,你可以尝试使用
let linkType: typeof Link
您希望实现这一目标的用例是什么?我之所以问,是因为我很困惑为什么你想要一个自定义链接,而不是一个自定义锚组件,如果锚标签包装了一个反应功能零件。我问的原因是因为我遇到了一个问题,我试图用数据(卡片)包装一个功能组件,如下所示:
<>
<Link
passHref
href={`/services/[slug]`}
as={`/services/${encodeURIComponent(
popservice.node.slug
)}`}
scroll={true}
>
<a className='block' key={i++}>
<ServiceTopTemplate service={popservice.node} />
</a>
</Link>
</>
这并不是完美无缺的,经过一番挖掘,我发现如果你用Link->a->FC 包装一个诸如ServiceTopTemplate 的功能组件,你需要一个带有forwardedRef 的锚组件来路由到正确嵌入锚中。所以,我通过使用 forwardedRef 制作一个不可知的、可重用的 Anchor 组件来解决这个问题
<>
<Link
passHref
href={`/services/[slug]`}
as={`/services/${encodeURIComponent(
popservice.node.slug
)}`}
scroll={true}
>
<Anchor className='block' key={i++}>
<ServiceTopTemplate service={popservice.node} />
</Anchor>
</Link>
</>
自定义Anchor组件定义如下:
import mergeRefs from 'react-merge-refs';
import { LoadingSpinner } from '@/components/UI';
import cn from 'classnames';
import css from './anchor.module.css';
import React, {
FC,
CSSProperties,
AnchorHTMLAttributes,
useRef,
JSXElementConstructor
} from 'react';
import { Url } from 'url';
// Omit intrinsic href to reinject with conditional Url interface to accept query hrefs from next/link
// query hrefs, e.g.: href={{ query: { slug }, pathname: '', href: '', { ...options, etc } }}
export interface ForwardedAnchorProps<T = HTMLAnchorElement>
extends Omit<AnchorHTMLAttributes<T>, 'href'> {
className?: string;
Component?: string | JSXElementConstructor<any>;
width?: string | number;
variant?: 'flat' | 'slim';
loading?: boolean;
type?: 'submit' | 'link' | 'active';
href?: string | Url;
active?: boolean;
disabled?: boolean;
style?: CSSProperties | {};
}
// this component serves to wrap imported functional components -- allows for proper embedding of href in browser when
// wrapping functional components with Link and anchor, respectively
const Anchor: FC<ForwardedAnchorProps<HTMLAnchorElement>> =
React.forwardRef((props, aRef) => {
const {
onClick,
width,
className,
href,
active,
style,
variant = 'flat',
disabled = false,
loading = false,
Component = 'a',
children,
...rest
} = props;
const ref = useRef<typeof Component>(null);
const rootClassName = cn(
css.root,
{
[css.slim]: variant === 'slim',
[css.loading]: loading,
[css.disabled]: disabled
},
className
);
return (
<Component
aria-pressed={active}
disabled={disabled}
ref={mergeRefs([ref, aRef])}
className={rootClassName}
onClick={onClick}
href={href}
style={{ width, ...style }}
{...rest}
>
{children}
{loading && (
<i className='pl-2 m-0 flex'>
<LoadingSpinner className='transform-gpu transition-all duration-150 animate-spin' />
</i>
)}
</Component>
);
});
export default Anchor;
对应css文件的内容:
.root {
@apply cursor-pointer block transition-all ease-in-out duration-150 transform-gpu;
}
.root:hover {
@apply bg-redditBG;
}
.root:focus {
@apply outline-none;
}
.root[data-active] {
@apply hover:bg-redditBG;
}
.loading {
@apply bg-current text-olive-300 border-redditBG cursor-not-allowed;
}
.slim {
@apply py-2 transform-none normal-case;
}
.disabled,
.disabled:hover {
@apply text-olive-400 border-redditBG bg-current bg-opacity-90 cursor-not-allowed;
filter: grayscale(1);
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
更新 -- 重新检查您的代码后,尝试更改此代码:
<button>{item.title}</button>
到这里:
<a><button>{item.title}</button></a>
那么它可能会起作用