动态道具依赖于其他道具

Posted

技术标签:

【中文标题】动态道具依赖于其他道具【英文标题】:Dynamic props depending on other prop 【发布时间】:2021-12-20 00:34:45 【问题描述】:

我有这个组件,它只是一个标题和右边的一个图标,这个组件的容器可以是一个按钮,一个锚元素,或者来自react-router-dom的一个Link元素。

我能够像这样动态创建容器:

import  Link  from "react-router-dom";
// ....
type Props = 
  as: "button" | "a" | "Link";
  title: string;
  icon: string;
;
const ActionItem: React.FC<Props> = ( as, title, icon : Props) => 
  const Container = styled(as === "Link" ? Link : as)`
    display: flex;
    // ...
  `;

  return (
    <Container>
      title
      <div style= flex: 1  />
      icon
    </Container>
  );
;

但是现在我想要完成的是根据as 属性来获得动态道具,例如,如果as 道具等于Link,则显示链接组件的所有道具比如toreplace等。或者如果as等于a,则显示锚元素的所有道具,比如hreftarget等。

<ActionItem 
  as="Link"
  to="/profile"
  ...
/>

我尝试了this,但没有成功,主要是因为在示例中他们使用的是原生 html 元素,而我需要使用这些(按钮和锚元素)加上 Link 组件。

我不知道我试图找到的是否可行,或者这是否是另一种可能的解决方案?

顺便说一句,here's a code sandbox 带有代码

编辑: 这是代码的sandbox 应该正常工作

【问题讨论】:

出于好奇,我想知道您是如何在盒子上获得这种素描效果的? 我用excalidraw,它是一个在线绘图工具 其实我想实现和excalidraw一样的效果,但是我不想深入研究他们的源代码(他们是如何在画布中做到的),所以我猜你已经实现了一个包什么的:)。 【参考方案1】:

您应该使用所谓的discriminating union(或歧视性联合)。让我们使用as 属性作为鉴别器。

你已经有了

type Props = 
    as: "button" | "a" | "link"

把它分开

type Props = 
     as: "button"  | 
     as: "a"  | 
     as: "Link" 

现在只需向联合的每个部分添加您期望的道具,以便 Typescript 推断出其他可能的属性,给定鉴别器道具as

type Props = 
     as: "button"  & ButtonProps | 
     as: "a"  & AProps |
     as: "Link"  & LinkProps

完成!

顺便说一句,我为您需要的互补道具使用了虚构的名称,您必须查找要与您的鉴别器道具相交的类型的名称。

【讨论】:

以上是关于动态道具依赖于其他道具的主要内容,如果未能解决你的问题,请参考以下文章

Vue 和重复的道具

如何在单个文件 vue 组件中的初始化时将道具传递给 vue 组件(vue-loader 中的依赖注入)?

如何在组件的方法中访问 Vue JS 道具?

道具不变怎么看?

未显式声明的 Vue 道具

为啥 Textfield 控件不采用道具(类)?