为React组件编写API,第1部分:不要创建冲突的道具
编写用于React组件的API,第2部分:为行为命名,而非交互
为React组件编写API,第3部分:道具的顺序很重要
编写用于React组件的API,第4部分:当心提示!
编写用于React组件的API,第5部分:使用组合
我们为React组件编写API,第6部分:在组件之间创建通信
让我们谈谈Avatar
组件。

<Avatar image="simons-cat.png" />
化身在应用程序中随处可见,通常大小不同。 用户配置文件需要一个大头像,下拉列表中需要一个小头像,中间还有几个。

让我们添加道具size
( size
道具)。
我们不想给开发人员指定任意宽度和高度的能力;相反,我们想给开发人员几个可能的尺寸。

<Avatar size="xsmall" image="simons-cat.png" /> <Avatar size="small" image="simons-cat.png" /> <Avatar size="medium" image="simons-cat.png" /> <Avatar size="large" image="simons-cat.png" /> <Avatar size="xlarge" image="simons-cat.png" />
在cosmos中 ,我们仍然有应用程序的化身。 我们希望它们看起来有些不同-圆角正方形而不是圆形。
创建良好的API的一部分是使开发人员能够考虑数据而不是设计-设计应该已经在组件中
我们可以添加另一个区分两种化身的道具。 一个小道具不会伤害,对不对?

<Avatar type="user" image="simons-cat.png" /> <Avatar type="app" image="firebase.png" />
看起来不错,不是吗?
是的,我们获得了对应用程序头像的多种支持,因为它是相同的组件。 总的来说,我们不需要这个,但为什么不这样做,因为它没有花我们任何钱

<Avatar type="app" size="xsmall" image="firebase.png" /> <Avatar type="app" size="small" image="firebase.png" /> <Avatar type="app" size="medium" image="firebase.png" /> <Avatar type="app" size="large" image="firebase.png" /> <Avatar type="app" size="xlarge" image="firebase.png" />
让我们谈谈开发人员将如何在其应用程序中实际使用此组件。 用户信息可能来自API,并且包含化身的URL。 开发人员将使用道具将此信息传递给Avatar
组件。
如果用户尚未上传头像,我们想显示默认值,应用程序徽标也是如此。

<Avatar type="user" image={props.user.avatar} /> <Avatar type="user" image={missing} /> <Avatar type="app" image={props.app.logo} /> <Avatar type="app" image={missing} />
默认图像已包含在组件中,因此我们不要求开发人员提供默认图像。
这是一个很好的后备,但我们可以做更多。
我们可以显示具有唯一背景的用户名的缩写(Gmail使此模板流行,它有助于快速区分人)

<Avatar type="user" image={props.user.avatar} /> <Avatar type="user" image={missing} /> <Avatar type="user" initials={props.user.intials} image={missing} /> <Avatar type="app" image={props.app.logo} /> <Avatar type="app" image={missing} /> <Avatar type="app" icon={props.app.type} image={missing} />
让我们看一下组件支持的所有道具:
我们从一个简单的头像组件开始,但是现在它支持所有这些道具和行为!
当您看到支持许多道具的组件时,它可能正在尝试做太多事情。 您刚刚创建了Apropcalypse 。
由Jenn Creighton提出了这个概念。
我们正在努力使Avatar
组件可为用户和应用程序使用,同时为不同的后备行为使用不同的大小和不同的选项。
它还允许使用不推荐使用的奇怪组合,例如备用文本应用程序头像。 请记住,这是技巧1- 不要创建冲突的道具 (请参阅为React组件编写API,第1部分:不要创建冲突的道具 )!
好吧,我们该如何处理? 创建两个不同的组件。
提示:
不要害怕创建一个新组件,而不是向现有组件添加道具和其他逻辑。
首先,这是两个不同的头像组件的API外观:

<UserAvatar size="large" image="simons-cat.png" /> <UserAvatar size="large" image="" /> <UserAvatar size="large" fallback="LA" image="" /> <AppAvatar image="firebase.png" /> <AppAvatar image="" /> <AppAvatar fallback="database" image="" />
此API中有几件事值得注意:
- 我们能够删除
AppAvatar
中不必要的功能,例如size
。 - 我们通过为两个组件保留相同的
fallback
名称(fallback)来减小API的大小 。
还记得本系列的技巧2吗? 我们希望开发人员考虑行为( fallback
),而不考虑交互/实现(缩写或图标) 。 这有助于开发人员更快地学习API和使用组件的方式。 - 我们还可以避免任何冲突的道具 。
- 最后,我们减少了道具的数量。 看一下道具表,它变得更加干净:
UserAvatar:
AppAvatar:
令我烦恼的是,尽管这两个组件的fallback: string
名称和类型相同,但它们的名称和类型相同fallback: string
( fallback: string
类型的fallback: string
是字符串),其中之一的首字母取两个字母,而时间与图标的名称相同。
让我们谈谈实现。 试图创建同时使用UserAvatar
和AppAvatar
的BaseAvatar
组件很诱人,而某些道具将被阻止。
function UserAvatar(props) { return ( <BaseAvatar image={props.image} type="user" initials={props.fallback} /> ) } render(<UserAvatar fallback="LA" />)
这根本不是一个坏主意。 但是从一开始就很难预测我们可能需要什么。 我们很难预测未来的需求。
从两个不同的组件开始,并且在开发它们时,您可以开始看到相似的模式并找到一个好的抽象。 缺少抽象比不正确的抽象要好得多。
复制比不正确的抽象要好-Sandi Metz
回到您的代码,找到需要太多道具的组件,看看是否可以通过将其分成几个组件来简化它。
进一步研究:
- 珍妮·克雷顿(Jenn Creighton)的演讲 ,她在那儿谈论阿波罗卡利普斯
- Sandi Metz关于重复和抽象的演讲