Clean Frontend Architecture:整洁前端架构 | clean-frontend

https://github.com/eduardomoroni/react-clean-architecture

https://github.com/im-a-giraffe/angular-clean-architecture

https://github.com/phodal/clean-frontend

https://github.com/android10/Android-CleanArchitecture

总结

权限控制怎么放置?路由首位中?

模块化,modules自动加载,如route/modules

通过配置化方式,路由能力的增强,meta.roles 可进行路由权限控制

vue-element-admin阅读

permission 有菜单路由级别,按钮级别,

https://github.com/PanJiaChen/vue-element-admin/tree/master/src

vue-element-admin

vue-vben-admin 项目阅读

router路由,路由配置和路由守护

enums 常量,

design 样式

api

logics

settings

hooks

store

utils

里面还各有各种分层,命名很清晰

**

**

看入口文件, main.ts

  • 有点应用程序的感觉, bootstarp() ,需要先启动加载很多部分,然后才能执行 app.mount 加载渲染


  1. // 核心的启动函数
  2. async function bootstrap() {
  3. const app = createApp(App);
  4. // Configure store
  5. setupStore(app);
  6. // Initialize internal system configuration
  7. initAppConfigStore();
  8. // Register global components
  9. registerGlobComp(app);
  10. // Multilingual configuration
  11. await setupI18n(app);
  12. // Configure routing
  13. setupRouter(app);
  14. // router-guard
  15. setupRouterGuard();
  16. // Register global directive
  17. setupGlobDirectives(app);
  18. // Configure global error handling
  19. setupErrorHandle(app);
  20. // Mount when the route is ready
  21. // https://next.router.vuejs.org/api/#isready
  22. await router.isReady();
  23. app.mount('#app', true);
  24. }
  25. void bootstrap();

入口文件 App.vue

  1. <template>
  2. <ConfigProvider :locale="getAntdLocale">
  3. <AppProvider>
  4. <RouterView />
  5. </AppProvider>
  6. </ConfigProvider>
  7. </template>

AppProvider是做什么用?为何不直接使用一个Store来管理变量和逻辑?以及ConfigProvider的作用

核心路由 router 路由配置增强

  • guard
  • helper
  • menus
  • routes
  • index.ts

路由守卫做了什么?

初始化逻辑,获取当前url状态在哪里?应该在store中,还是router中?

vscode中都是在一起,在bootstrap代码中,有restore逻辑

basicMenu中有 listenerRouteChangesetOpenKeys ,有设置菜单展开的逻辑,handleMenuChange中有 setOpenKeys

如果菜单变更, items

路由模块化,路由配置增强

写在modules中,会被自动加载

里面包含了很多逻辑,如权限控制的 meta.roles

路由配置还包含了各种配置项,

菜单文件 Menu 菜单初始化激活 菜单更变逻辑

layout的结构

也是层层结构,需要控制折叠展开,菜单根据打开的url初始化激活,

image.png

当前激活的菜单,如过url中有hash或path,需要初始化展开的菜单

初始化时,获取并激活当前应该展开的菜单

SimpleMenu.vue

和菜单变更的逻辑都集中化

  1. const { setOpenKeys, getOpenKeys } = useOpenKeys(
  2. 1 展开相关的变化
  3. watch(
  4. () => props.collapse,
  5. (collapse) => {
  6. if (collapse) {
  7. menuState.openNames = [];
  8. } else {
  9. // 激活当前应该展开的菜单
  10. setOpenKeys(currentRoute.value.path);
  11. }
  12. },
  13. { immediate: true }
  14. );
  15. 2 侧边栏items的变化
  16. watch(
  17. () => props.items,
  18. () => {
  19. ...
  20. setOpenKeys(currentRoute.value.path);
  21. },
  22. { flush: 'post' }
  23. )
  24. // 路由相关的变化
  25. listenerRouteChange((route) {
  26. handleMenuChange(
  27. if(...) {
  28. setOpenKeys()
  29. }
  30. });
  31. async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
  32. async function handleSelect(key: string) {

网络请求 utils/http/axios

  1. index.ts 入口

**
初始化VAxios,传入业务

并通过transform定制了业务逻辑

transformRequestHooks 后hook,根据code统一的错误弹窗,登录超时的错误提示。

responseInterceptorsCatch 的调用checkStatus,根据网络错误code,展示友好的中文提示。

requestInterceptors 在header中添加token

  1. Axios.ts 封装了VAxios,

Axios做了什么?

  • 对外暴露一些定制参数,如接口url,是否忽略重复请求等,背后添加的是辅助的能力

  • 对外暴露了transform参数,抽象了请求过程的几个生命周期,供外部进行定制。

    • beforeRequestHook 请求前hook, transformRequestHook ,请求后hook
    • requestInterceptors 请求前拦截器, responseInterceptors 请求后拦截器
    • requestInterceptorsCatch 请求前拦截错误处理, responseInterceptorsCatch
  • 封装了upload上传文件的util

  1. checkStatus.ts

这个逻辑独立出来,在

Logics?

errorHandle

mitt/routeChange

theme

Hooks 很多逻辑都封装在这里

vue自身也使用了很多hooks的封装

  1. import { useRouter } from 'vue-router';
  2. setup(props, { attrs, emit }) {
  3. // 这个currentRoute拿到的是响应式的变量
  4. const { currentRoute } = useRouter();
  5. }

event/useBreakPoint.ts 封装了窗口大小改变的自适应逻辑

一些有用的hooks

useModal

useTable

一些逻辑的封装hooks

顶上的折叠,展开侧边栏的功能。底层数据保存在 vuex 中的 appStore 中,但是不会通过 commit 等方式直接修改数据。而是通过useMenuSetting,提供了方便的get和set的相关API。

  1. // HeaderTrigger
  2. // SidebarTrigger
  3. setup(){
  4. const { getCollapsed, toggleCollapsed } = useMenuSetting();
  5. return { getCollapsed, toggleCollapsed };
  6. }
  7. // useMenuSetting.ts
  8. import { useAppStore } from '/@/store/modules/app';
  9. const appStore = useAppStore();
  10. const getCollapsed = computed(() => appStore.getMenuSetting.collapsed);
  11. // Set menu configuration
  12. function setMenuSetting(menuSetting: Partial<MenuSetting>): void {
  13. appStore.setProjectConfig({ menuSetting });
  14. }
  15. function toggleCollapsed() {
  16. setMenuSetting({
  17. collapsed: !unref(getCollapsed),
  18. });
  19. }

权限 Permession逻辑

底层还是用vuex来存储,商城用usePermisson来提供hooks

  1. // usePermission.ts
  2. import { usePermissionStore } from '/@/store/modules/permission';
  3. // 使用Permission的地方
  4. import { usePermission } from '/@/hooks/web/usePermission';
  5. const { changeRole, hasPermission, togglePermissionMode, refreshMenu } = usePermission();

store/modules/user.ts

login

有内层和外层的 try catch 的处理

logout

阅读的感受

入口清晰,整个应用的 main.tsApp.vue ,每个模块部分的 index.ts

逻辑清晰,由浅入深,抽象层次一致,如main.ts中的bootstrap()代码,如 router/guard/index.ts

封装,对外暴露参数,如 axios部分 ,业务逻辑和定制部分,都在 index.ts 中可阅读到,其它部分都封装了依赖。

命名,分类清晰
**

  1. // 配置,项目配置
  2. import projectSetting from '/@/settings/projectSetting';
  3. // app常亮
  4. import { PermissionModeEnum } from '/@/enums/appEnum';
  5. // 基础的路由
  6. import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
  7. // sys系统相关的接口
  8. import { getMenuList } from '/@/api/sys/menu';
  9. import { getPermCode } from '/@/api/sys/user';


都模块化,方便维度

router/routes/modules
router/menus/modules
store/modules

异常处理

LoginFormuserStore.login 的逻辑

有哪些缺点?

逻辑分散?

AppProvider 中有 createBreakpointListen 开启自行应逻辑

SimpleMenu 中有 菜单初始化激活,也许放一起更好?

业务逻辑都写在了store中,如userStore中的login包含了 登录请求,获取用户信息等复杂业务逻辑。是否应该有个service来做处理。

antd pro

登录逻辑,都在redux的effects中,

https://github.com/ant-design/ant-design-pro/blob/master/src/models/login.ts

modles/login

login()
logout()

权限管理 - Ant Design Pro

umijs

@umijs/plugin-access

angular-clean-architecture

im-a-giraffe/angular-clean-architecture: This repository demonstrates a basic way how to implement the clean architecture pattern introduced by Uncle Bob to web apps like Angular.

Ng-alain

https://github.com/ng-alain/ng-alain/