link

const resolveToLocation = (to, currentLocation) =>
    typeof to === "function" ? to(currentLocation) : to;

const normalizeToLocation = (to, currentLocation) => {
    return typeof to === "string"
        ? createLocation(to, null, null, currentLocation)
        : to;
};
// React 15 compat
const forwardRefShim = C => C;
let { forwardRef } = React;
if (typeof forwardRef === "undefined") {
    forwardRef = forwardRefShim;
}

function isModifiedEvent(event) {
    return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
}

const LinkAnchor = forwardRef(
    (
        {
            innerRef, // TODO: deprecate
            navigate,
            onClick,
            ...rest
        },
        forwardedRef
    ) => {
        const { target } = rest;

        let props = {
            ...rest,
            onClick: event => {
                try {
                    if (onClick) onClick(event);
                } catch (ex) {
                    event.preventDefault();
                    throw ex;
                }

                if (
                    !event.defaultPrevented && // onClick prevented default
                    event.button === 0 && // ignore everything but left clicks
                    (!target || target === "_self") && // let browser handle "target=_blank" etc.
                    !isModifiedEvent(event) // ignore clicks with modifier keys
                ) {
                    event.preventDefault();
                    navigate();
                }
            }
        };

        // React 15 compat
        if (forwardRefShim !== forwardRef) {
            props.ref = forwardedRef || innerRef;
        } else {
            props.ref = innerRef;
        }

        /* eslint-disable-next-line jsx-a11y/anchor-has-content */
        return <a {...props} />;
    }
);

/**
 * The public API for rendering a history-aware <a>.
 */
const Link = forwardRef(
    (
        {
            component = LinkAnchor,
            replace,
            to,
            innerRef, // TODO: deprecate
            ...rest
        },
        forwardedRef
    ) => {
        return (
            <RouterContext.Consumer>
                {context => {
                    invariant(
                        context,
                        "You should not use <Link> outside a <Router>"
                    );

                    const { history } = context;

                    const location = normalizeToLocation(
                        resolveToLocation(to, context.location),
                        context.location
                    );

                    const href = location ? history.createHref(location) : "";
                    const props = {
                        ...rest,
                        href,
                        navigate() {
                            const location = resolveToLocation(
                                to,
                                context.location
                            );
                            const method = replace
                                ? history.replace
                                : history.push;

                            method(location);
                        }
                    };

                    // React 15 compat
                    if (forwardRefShim !== forwardRef) {
                        props.ref = forwardedRef || innerRef;
                    } else {
                        props.innerRef = innerRef;
                    }

                    return React.createElement(component, props);
                }}
            </RouterContext.Consumer>
        );
    }
);
  1. link 组件是一个 Consumer,接受 Router 组件传递的 context
  2. link 组件默认创建一个 a 标签,或者自己传一个自定义组件
  3. 如果传 replace, 点击的时候就调用history.replace,否则调用history.push

results matching ""

    No results matching ""