现在在用 vue 和 ui 框架做一个 xxx 管理系统,说实话在我看来就是增删改查贴数据,也会用到 echart 等常规插件。这些工作很多时候都十分重复,我个人觉得这样成长速度会很慢。所以想问一下,前端应该怎么做,才能做得深入,仅仅是做个 xxx 管理系统的页面,以及深入以后的前端,究竟是什么样子的。我想知道关于前端的一些。来吧大佬们,给我点知识和希望 – 知乎提问

现在市面上流行的组件库,其实严格来说还是偏底层的抽象,以组件为单元解决视觉交互和数据承载的问题,至于业务层它们是不去感知的。

而更复杂的情况反而是你说的增删改查这些偏业务的需求,而且就后台管理系统而言,其实很多公司,很多团队都想要把它做好,谁要是能作出一个公司级别的通用后台管理系统解决方案,那也是相当露脸的事情了。

是的,大部分工作确实如你所言是十分重复的,那既然如此可不可以通过上层设计把重复工作给屏蔽了?甚至让非前端开发都能方便地拿来就用。这个如果你没有实际经历过复杂的业务,或者帮助过非前端开发改过代码是无法想象这个问题的复杂度的。。

那咱们退而求其次,先把眼前的事给做好了,想想一个完善的管理系统应当是什么样子的:

一、统一、完整的交互规范

这个简单来说就是什么地方该用什么组件。比如,修改数据到底是用弹出框还是新页面;新增按钮是悬浮在页面底部还是统一在 action bar 中;confirm 行为是用 Modal 还是 Pop;页面哪些地方一定要有个标题;特定意义的图标和文字用什么颜色。

以上应当归属于用户体验优化:统一的交互才能产出完整的产品,完整的产品的所有反馈都是符合用户直觉和预期的。(我点的这个按钮一定会触发弹窗,点击右下角那个书本图标一定能看到帮助文档,刚刚这个错误提示肯定是网络故障)这可以让他们用起来莫名的爽!学习起来莫名的快!

二、更高级的业务抽象

管理系统随处可见的分页,查询、甚至是 tab 切换这些,你是否在大量的重复代码之后发现了它们的共同之处?那么尝试封装一个监听 query / hash 变化的生命周期?自动同步查询参数和 url query 的设计?

每次的修改操作是否都要调用校验?要不要 diff 出最小变化?提交的时候按钮要不要变成 loading?修改完成要不要重新请求数据?数据变更后要不要闪烁一下给个提示?涉及到图片,文件这些需要额外请求的字段可不可以像普通字段那样方便?如果你意识到了这些,是否可以开始封装一个统管这一切的 Modify 组件了?

对于网络请求,有没有考虑过缓存问题:从 http 协议到文件的打包、静态资源的请求、业务层的数据源缓存,甚至多页面多组件有可能涉及到的重复请求问题,有没有做过请求本身的复用?还有请求数据的 loading,超时,错误和成功后的数据格式化处理。是的,你可以开始封装一个 httpClient 组件了。

最后,那怕是纯业务层的代码,比如鉴权的设计:请求拦截和路由拦截,路由级别的控制和功能级别的控制以及和路由菜单的联动;还有大量相似行为的页面,如 DashBoard,各种列表页,有没有做过配置抽离和生命周期管理 再配合 mixin,extends,hoc 等抽象方式进行代码复用,如下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 采用继承的方式很多类似页面甚至不需要再实现生命周期方法
@Component
export default class DashboardXXX extends Dashboard {
dataItems = [
'DAU',
'ONEDAYDAU',
'TWODAYDAU',
'THREEDAYDAU',
'SEVENDAYDAU',
'THIRTYDAYDAU',
'WAU',
'MAU',
'USERVISCOSITY',
]
}

// 合理地使用Mixins几行代码就可以实现一个完备的支持分页/查询的页面
@Component({ mixins: [OnQueryUpdated] })
export default class LogsPage extends Vue {
pageData: LogPageData = { items: [], page: { maxPageIndex: 0 } }

async onQueryUpdated(query: Query) {
this.pageData = await httpClient.get<LogPageData>(
'/logs?' + query.toString(),
)
}
}

对于前端开发来说,还要有一些来自偏前端的执拗,比如授权页面跳转后我要回到跳转前的原本页面,甚至继续跳转前的行为,坚决不增加不必要的浏览历史。同理网页中某些地方提供的后退按钮,理论上你可以尽可能的后退到已经访问过的那个历史页,而不是再新开一个,即使是真的要新开,push 还是 replace url,这也是一个问题,包括 tab 页的切换也是,等等等吧。这维护的是一份用户可预期的浏览历史栈,这一点其实还可以参考下原生 app 的页面跳转,它能够做得更极致。

以上解决的是开发体验问题,设计的思想有点像 css 里的原子类 + 各种父级子集类,殊途同归,都是为了做更好的代码搬运工。所以我认为好的程序员一定要对重复代码嫉恶如仇,它可以驱动着你去做抽象,做设计,每一次干掉重复代码的过程其实就是水平提升的过程。暗示自己:我写的不是代码,是艺术!

三、可执行的约束

是的、以上两项设计你都做了,能不能很好地执行下去?无论是靠文档,靠工具还是靠开会,总之想想办法再解决一下人的问题吧。

说了这么多,有没有开始觉得就算是「增删改查」其实也是有不少事情可以搞一搞的?最后再贴两篇之前写过的相关文章,希望对看这篇回答的人有所帮助,也是对自己的一个总结。


 评论