- Published on
关于前端项目的思考
- Authors

- Name
- Li WenKang
- https://x.com/liwenkang_space
对于某一类特定的需求,过于原子化的组件化开发方式并不能够彻底地解决开发效率问题,从抽象的业务需求中能够具象出较为通用的可插拔可组合的技术方案才是解决实际问题的终极答案。
下面给出几个常见场景
页面布局方案
- 布局与路由的结合。如何实现不同路由不同布局?将布局组件作为
高阶组件传入不同的页面组件上 - 页眉:应用层页眉(数据传递给外面,不接收外层传入的数据),页面层页眉(数据从外层传入)
- 在企业管理系统中,作为一个应用级别的解决方案,能使用配置项解决的问题我们都应该尽量避免让使用者编写代码
- UI 与数据在架构时应当是
分离的,redux 作为二者之间的粘合剂,一旦二者通过 redux 被连接到了一起,那么这个组件也就不再纯净(pure)了,变为了只隶属于当前项目的一个业务组件且不再具备通用性 清晰的分层:应用层、布局层、页面层、组件层
权限管理机制
- 权限的设计:基于角色的访问控制(创建者/管理员/普通用户/游客)+ 访问列表控制(控制某个模块是否可见)
- 路由层面容器的管理:
- 区分需鉴权页面路由和无需鉴权页面路由(比如登录页面)
- 在需要登录鉴权的路由中通过
子组件(在 umi 中直接可用的),进行鉴权判断,当无权限的时候,跳转到登录页或提示无权限访问 - 对于无法匹配的路径,也要在页面提示用户404当前页面路径不存在
- 通过配置的方式,让路由的修改和新增都更容易处理了
- 注意权限管理部分的逻辑是
独立于页面的
文档目录树
- 每一层级都有一个唯一 id,且深层元素也要
有一个属性标识子集和所有上级(比如 path 属性: parentId/childId),从而实现菜单栏多级高亮。针对文档目录树,给节点增加带有上级节点标识的属性,对于后续在树上做增删改查操作有着极大的便利 - 利用 pathname 及 treeData 计算出当前的 selectedKeys/selectedNode,可以通过
Memoization优化这个过程 - 区分 props 和 state:props 从外部获得(组件内部无法计算出来),state 在组件内部(不应该被外部数据所改变)
消息通知的设计
- 应用层处理全局消息通知:登录完成后立即获取一次,后续使用 unread 接口轮询(此处 unread 接口还可以承担用户超时后,发送请求,触发超时等出的逻辑,但这么搞的话,也相当于违反了单一职责原则,需在具体场景具体分析)
- 数据驱动视图:当有未读消息的时候,自动展示
归根结底其降低内部复杂度的方式就是分层。通过不断地分层将整体复杂度合理地分散在每一个模块中并将其封装起来,从而达到极大地降低拼接不同模块时复杂度的目的
对于任意一个模块来说,衡量其优秀程度的维度有三点
- 能否和当前系统配合起来完成具体任务
- 这个模块是否和其上下游的模块强耦合,即其他模块是否需要为了适应它而做出特殊的调整。好的模块是为其他模块赋能的,即赋予其他模块更多的能力而不需要其他模块做出任何的妥协或牺牲。
- 这个模块是否能够无缝地迁移到其他的系统并完成同样的工作。这就涉及软件工程中经常讲的可复用性,即一个模块自身的封装是否足够优秀以至于并不会因为所处系统的不同而需要做特殊的调整。