Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

留个言 #45

Closed
LonelyFellas opened this issue Sep 14, 2023 · 10 comments
Closed

留个言 #45

LonelyFellas opened this issue Sep 14, 2023 · 10 comments

Comments

@LonelyFellas
Copy link

fork,下来,应是没启动起来,本来想提个pr的。怎么办

@jaywcjlove
Copy link
Member

@LonelyFellas

第1步:在根目录安装依赖 npm i
第2步:在根目录监听编译包文件 npm run watch
第3步:在根目录运行 npm run doc 启动文档网站,同时可以实时预览示例进行测试

@LonelyFellas
Copy link
Author

import { Children, Fragment, createElement } from 'react';
import type { FC, PropsWithChildren, ReactElement } from 'react';
type ElementLabel = keyof JSX.IntrinsicElements;

type ElementRef<T extends ElementLabel> = JSX.IntrinsicElements[T] extends React.DetailedHTMLProps<
  React.HTMLAttributes<unknown>,
  infer A
>
  ? A
  : never;
/**
 * 增加一个可选参数strict,默认为True。
 * * 当strict为true时,Switch只会渲染Case为True的组件或者Default组件,其他任意子节点都不渲染
 * * 反之,Switch除了Case为False的组件不渲染,其余子节点都渲染
 *
 *
 * 增加一个可选参数label
 * * 如果你想当在Switch当作一个正常的标签的话,可以给label传入相对应的标签名字 如:div span h1
 * * 同时也可以接受与之对应的事件 如:onClick onMouseEnter onMouseLeave
 * * label不传,则Switch相当于一个Fragment
 * *
 *
 * @param param0
 * @returns
 */

interface SwitchProps<T extends ElementLabel>
  extends React.DetailedHTMLProps<React.HTMLAttributes<ElementRef<T>>, ElementRef<T>> {
  strict?: boolean;
  label?: T;
}

export function Switch(props: PropsWithChildren<{ strict?: boolean }>): ReturnType<FC>;
export function Switch<T extends ElementLabel>(props: PropsWithChildren<SwitchProps<T>>): ReturnType<FC>;
export function Switch<T extends ElementLabel>(props: PropsWithChildren<SwitchProps<T>>): ReturnType<FC> {
  const { strict = true, label, children, ...restProps } = props;
  /**
   * 我觉得这里应该用个数组来接,因为当有多个Case为true的情况会要考虑
   */
  let matchChild: ReactElement[] = [];
  let defaultCase: ReactElement | null = null;
  Children.forEach(Children.toArray(children) as ReactElement<PropsWithChildren<CaseProps>>[], (child) => {
    if (strict === true) {
      if (child.type === Case && child.props.condition === true) {
        matchChild.push(child);
      } else if (!defaultCase && child.type === Default) {
        defaultCase = child;
      }
    } else {
      if (!(child.type === Case && child.props.condition === false) && child.type !== Default) {
        matchChild.push(child);
      } else if (!defaultCase && child.type === Default) {
        defaultCase = child;
      }
    }
  });
  return createElement(
    label || Fragment,
    label === undefined && restProps === undefined ? {} : { ...restProps },
    matchChild.length !== 0 ? matchChild : defaultCase,
  );
}

export interface CaseProps {
  readonly condition?: boolean;
}

export const Case: FC<PropsWithChildren<CaseProps>> = ({ children }) => children;
export const Default: FC<PropsWithChildren> = ({ children }) => children;

@LonelyFellas
Copy link
Author

你看看这个需求能不能值的提pr。

@jaywcjlove
Copy link
Member

对 Switch 增加了俩个 API strict, label,在渲染 Case 或者 Defaultstrict 没有必要,这个组件原本来源于 Switch 语法,strict 破坏了这个语法。

label props 我觉得可以添加,但是不应该添加在 Switch 组件上,应该添加到 Case 或者 Default

<Switch>
    <Case as="span" condition={age < 6}>Preschool</Case>
    <Case as="em" condition={age >= 6 && age < 18}>Primary school</Case>
    <Case as="div" condition={age >= 18}>Went to college</Case>
    <Default as="p">you graduated</Default>
</Switch>

如果有空估计实现方法可能需要改变,因为里面用的一些 API 未来可能过时

image

@LonelyFellas
Copy link
Author

OK, 我有时间把你刚才的功能的实现一下,去掉strict,将label参数移到Case和Default节点上,同时更换过时的API

@jaywcjlove
Copy link
Member

@LonelyFellas 感谢提交 PR,这可以学习新语法,替换过时的语法并不容易,我这里给个思路

在 Switch 上维护一个 Context,在 Case 或者 Default 组件上,将 props 存储到 Context,使用 useId 为 Case 和 Default 生成唯一 id,在 Switch 上循环渲染它

这是我提供的一个思路,或许有更好的思路和办法,欢迎提交 PR

@LonelyFellas
Copy link
Author

@jaywcjlove 果然大佬就是大佬。思路敏捷和清楚,我get到了,我晚上实现一下。你还有一下项目keywords我也想提pr的。我先把这个实现一下。

@jaywcjlove
Copy link
Member

@LonelyFellas 我实现了 as 的效果

jaywcjlove added a commit that referenced this issue Sep 23, 2023
@LonelyFellas
Copy link
Author

@jaywcjlove 这事情我给忘记了。😄

@jaywcjlove
Copy link
Member

@LonelyFellas 更新 v2 拥有这一特性

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants