首页 > 实习半年后再看经典面试题:如何封装一个组件
头像
lxylxy_
发布于 04-01 10:44
+ 关注

实习半年后再看经典面试题:如何封装一个组件

前端同学们如果面试多的话可能会被问过这个问题:封装过组件不?你是怎么封装的?或者:如何封装一个组件?

忘记哪一次面试了,我也被问到过这个问题,当时答的并不好,粗略讲了一下我理解的流程。下来又问了一下豆包,给出的答案是这样的

面试官真的就只是想听一下这种无聊的最基础的流程吗?我觉得不是。最近做的需求刚好封装了一个通用组件,那天走在路上想要写什么话题,突然想到这个,那就看下实习到现在的我,回头看这个问题又有哪些理解,大家可以看下我的思路,并结合自己的一些理解,尽可能完美的给面试官解答这个问题(下文若涉及到技术栈皆以React为例,Vue同理类比即可)。

首先,在进行组件封装之前,我们要明确一个点:我们要封装的是否是一个通用组件。

为什么要明确这个点?因为是否是一个通用组件会涉及到很多内部逻辑的书写,包括接口和hook的定义和使用。如果你是封装一个只有自己使用的组件,那么你的数据获取可以直接在组件内部调用接口,这样就可能不需要在props中预留传数据参数的属性。如果你封装一个通用组件,除了数据应当通过props传入以外,你还需要考虑组件放在什么位置,需要预留哪些props属性,让后续使用者尽可能的好复用。好的组件一定是要有足够强的可维护性和足够方便的可使用性的。

上面的这段话没有实习过的同学可能觉得有点抽象,我给大家举个case:

假设你有一个系统,系统中有一个审批模块,审批模块中可以用到的审批按钮在整个模块中的逻辑包括交互都应当是一样的,这样的一套按钮应当被封装为一个通用组件,方便各审批页面进行使用。这样的话,你在封装这个组件时就应当预留至少以下几个属性:1.需要审批的内容信息;2.审批后调用的方法或者函数(比如刷新table,刷新页面,跳转页面等),除此之外根据业务场景可能还需要加一些定制化的属性比如用户信息以方便获取权限等等。所有需要通过请求得到的审批内容信息应当从接口获取并通过props传入组件,而如果是非通用接口则可以在组件内部调用接口获取。

明确了这个组件是否是通用组件后,就要看这个组件会用在什么位置,如果只是你这个页面使用,那就放在当前页面组件同层级或组件文件夹下的component文件夹中,如果是通用组件,那么就应当定义在共用的定义组件的位置。以我们的项目为例,使用微前端架构,多个子应用想要共同使用同样的组件时就会从shared-component这样一个单独的文件夹中获取组件。并且我们由于考虑到发包的问题,使用shared-component中的组件使用的是产物引入,而自己页面使用的组件通常使用直接引入(这并不意味着通用组件就必须使用产物引入,具体的引入方式还是要看项目本身使用什么比较方便或者有没有什么发包诉求)

这里顺便提一下产物引入和直接引入的区别。

  • 直接引入顾名思义,就是直接引用你写的组件,比如import Component from './my/Component.tsx';而产物引入就是引用经过构建、编译或者打包等操作后生成的产物。例如在前端项目中,引用经过 Webpack 打包后的 JavaScript 文件。以我们shared-component为例,在这里定义的时候我们会将这些定义的组件都通过index文件导出,由于要导出很多的组件内容,所以意味着你的组件只能使用具名导出,不能使用默认导出
  • 直接引入的好处:直接引用具有较高的灵活性,你可以随时修改组件,并且hmr会立即生效。但产物引入的话,由于每次改动都需要打包才能生效,因此开发过程中调整的效率比较低。
  • 产物引入的好处:可以发包(npm/pnpm等)。发包意味着依赖的引用是稳定的,不会轻易产生依赖冲突。这在微前端项目中及其有用,试想项目中的子应用可能各应用使用的依赖版本都不一样甚至技术栈都不一样,那么直接引用的话可能就会出现依赖版本冲突,这个问题还是相对常见的,而使用产物引入一般不用考虑这个问题,只需要考虑你引用的产物版本是否正确即可。

回到问题本身,接着就是定义入参,定义入参的时候,通用组件需要跟其他模块的同学对好字段,预留好props字段。定义hooks、type和const时也应当单独定义并导出方便后续同学使用。再后面就跟豆包说的差不多了,写内部逻辑,写组件样式,导出并引用。

所以这段时间我对这个问题的思考主要是集中在定义组件是否是通用组件以及二者的区别上,在面试时提到这一差别可能会让面试官感到耳目一新,并且凸显自己的思考。也许就是这一个亮点,可以覆盖你前面的许多瑕疵。

全部评论

(1) 回帖
加载中...
话题 回帖

近期热帖

热门推荐