Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue 2.x 项目实践 #7

Open
leopen-hu opened this issue Dec 21, 2017 · 4 comments
Open

vue 2.x 项目实践 #7

leopen-hu opened this issue Dec 21, 2017 · 4 comments

Comments

@leopen-hu
Copy link
Owner

leopen-hu commented Dec 21, 2017

技术选型

  • 主要技术:vue 2.x + iview + vuex + vue-router + axios
  • 脚手架:vue-cli
  • 辅助库:lodash, moment.js
@leopen-hu
Copy link
Owner Author

leopen-hu commented Dec 21, 2017

演化过程

  • 第一阶段:直接使用脚手架模板
    直接使用 vue-cli 模板创建项目,控件库使用 iview,路由组织使用 vue-router,使用 axios 作为 http 请求库并作简单封装,因为后台 admin 的逻辑复杂度我们一开始认为是比较简单的,没有引入 vuex
  • 第二阶段:通过子父组件进行数据和事件的传递
    • props 绑定数据
    • v-on 绑定事件
    • 兄弟节点间的数据传递通过父组件转发
    • 父组件调用子组件的方法:使用 :ref 定位子组件后调用对应函数
  • 第三阶段:组件间数据交互太复杂,引入 vuex
    • 由于第二阶段在同一个模块下还算可用,但每个模块下代码重复量大且父组件中有大量数据交互逻辑,难以理解和维护,加上模块间数据调用在分析后发现不可避免,决定引入 vuex
    • 由于对于 vuex 的使用无经验,尝试管理全局状态(含界面状态),发现复杂度直线上升,不确定性太高
    • 商讨决定,现阶段只使用 vuex 对 api 返回的数据进行管理
  • 第四阶段:vuex 使用范围和方式的扩大
    • 多页面共享前台数据成为可以预见的常态(如查询条件在不同页面间的流转),部分界面数据存入
      store
    • vuex state 在内存中,导致刷新界面后丢失,会引发一些异常(如页面查询条件丢失),引入本地存储库 vuex-persistedstate,针对需要持久化的数据存入 localstorage

@leopen-hu
Copy link
Owner Author

leopen-hu commented Dec 22, 2017

目录结构

├── src/
│   ├── api/
│   │  ├── index.js
│   │  ├── api.js  // 对 axios 的简单封装
│   │  └── common-data.api.js  // 公用 api,可以根据接口,特性等划分
│   ├── components/
│   │  ├── index.js  // 注册公用组件
│   │  └── one-common-component.vue //公用组件
│   ├── router/
│   │  └── index.js // 总路由,注册局部路由
│   ├── utils/
│   │  └── utils.js  // 公用方法
│   ├── views/
│   │  ├── view-first/
│   │  │  ├── view-first.vue // 父容器,内含一个 router-view 用来加载模块下的不同页面组件
│   │  │  ├── view-first-list.vue  // 列表页
│   │  │  ├── view-first-detail.vue  // 详情、编辑、新增页(也可以拆分)
│   │  │  ├── view-first.router.js // 局部路由
│   │  │  ├── view-first.api.js // 局部 api
│   │  │  └── store/
│   │  │     ├── view-first.js // 局部store,需要注册到 vuex 的总 sotre
│   │  │     └── mutation_types.js
│   ├── vuex/
│   │  │  ├── store.js // 总 store,注册局部 store,公用数据 store
│   │  │  ├── actions.js
│   │  │  ├── getters.js
│   │  │  ├── mutation_types.js
│   │  │  └── modules/
│   │  │     └── common-data.js // 公用数据 store 过大时可以拆分成不同的 module
│   ├── App.vue
│   └── main.js
└── index.html

@leopen-hu
Copy link
Owner Author

leopen-hu commented Dec 29, 2017

现存问题

  1. 多请求的同时使用Promise.all结合mapAction会报错,已解决
created () {
    Promise.all([
      this.getCommonData({
        types: ['corporation', 'enum', 'businessPartner', 'currency', 'user', 'businessPlate', 'planSubject']
      }),
      this.getDepartmentList({})
    ])
  },
  methods: {
    ...mapActions(['getCommonData', 'getDepartmentList'])
  }

@leopen-hu
Copy link
Owner Author

发现的问题及解决方法

  1. 使用 vuex 不合理。

    • 问题1:引入 vuex 时机错误,合适的使用场景较少。
      描述:项目初始阶段,并没有积极和后端沟通,没有成型的 api 方案时就已经开始考虑前端架构的搭建了,在引入 vuex 时希望解决的是数据的跨页面交互问题,一个典型的场景就是列表页面选择一条数据跳转至编辑页面,不通过接口重新获取数据而是直接将数据从列表页传递至编辑页面。然而实际开发后,还是逐渐提供了单条数据的增删改查接口,这一场景的大量消失使引入 vuex 的优势不能体现(还存在一小部分功能由于 sap 的实现依然没有提供,比如资金计划提报就没有提供单条数据的查询接口)。
      解决方法:在发现该问题后后续模块不再使用局部 vuex store 来存列表数据,所有数据都缓存在组件内部。已完成的模块暂时不予变动。
    • 问题2:vuex 使用方式有误,不能保证状态变化的可预测性。
      描述:项目中存在很多传统的表单交互,使用了大量的双向绑定,并且直接绑定的对象是从 vuex store 中 mapState 过来的数据,所以实际上是直接更改了 store 中的数据。这一现象本应及时被发现,但由于刚接触时并不了解 vuex 中的配置,将其中一个配置项设置为 { strict: false } ,意味着并没有放开 dev 环境下 vuex 严格模式,因此没有报错。导致实际上对于 vuex 的使用基本上是违反了原则的,即没有保证数据更改的方法唯一性。
      解决方法:发现这一问题时,也是发现问题1的同时,由于后续不再大量使用 vuex 存储组件数据,所以各编辑页面的数据也是缓存在组件内部。针对部分正在开发的功能,使用组件内部数据缓存和 vuex 数据交互(deepClone)的方式处理(详见文章)。对于已经完成的功能暂时不予变动。
    • 问题3:整个 vuex 的 store 基本是当做全局变量在用。
      描述:项目开始时极力避免 .NET 中间层的数据冗余,所以所有的数据显示都是通过前端根据枚举值来格式化。然而随着开发的深入,发现这种机制的繁杂。特别是出现不是根据枚举值而是根据业务或基础数据本身再去查询的时候,前端不可能对大量数据进行缓存。中间甚至出现浏览器占用内存超过 1G 导致应用直接崩溃的极端情况。
      解决方法:通过业务、基础数据前端缓存来实现格式化的方式被废弃(数据量过大时)。通过 .NET 中间层查询业务数据后带出冗余字段的方式来实现。前端大数据量的缓存被清理,数据量较小的枚举等不予变动。改造后,前端缓存占用一般稳定在 200M - 300M 左右。
  2. 对于项目的预估不足。

    • 问题1:数据量大小
      描述:没有预估到部分基础数据会有数十万条之多,下拉框直接使用所有查询回来的数据导致页面卡死。同样的情况发生在数据格式化部分,不再重复说明。
      解决方法:使用异步下拉框的方法解决。当查询条件变化时,异步加载下拉数据,每次查询只会缓存 30 条。
    • 问题2:表单复杂度
      描述:在项目初期,基础数据部分的表单交互十分简单,编辑页面字段基本不超过20,复杂度较低,没有预估到后续业务功能的需求会有 100+ 字段的编辑页面的情况。而且业务流程的不同阶段,同一个界面显示不同字段,以及各个字段之间存在很多关联关系的情况都是刚开始没有预料到的。
      解决方法:由于用户操作习惯以及没有交互设计等原因,无法从源头去降低这些复杂度。开始的办法就是硬怼。后续模块有加强对模块内组件的抽取,文件分离等方式。虽然表单的复杂度没有下降,但文件的阅读和维护的复杂度在我个人看来是降低了的。
    • 问题3:组件复用基本没有
      描述:没有预估到很多统一的操作,其实有很多组件功能上基本相似,比如各种弹出框。基本每个模块都是自己直接在模块内实现,并没有抽取出共用组件或 mixin ,每个人的实现方式也不尽相同。就个人开发体验来说,重复代码量很大,体验很差。
      解决方法:在尽量保证开发进度的同时,尝试提取个人模块的公用组件。因为没有全局统筹的人可以去规划公用组件的功能,只能在个人模块下进行考虑复用。抽取了包括 弹窗 mixin,不同业务数据选择的 modal 组件,权限 mixin等。因为团队内部对组件化的认知不同,所以也没有很强的推动力,甚至还会有一些阻力,所以这些都只是一些不完善的尝试。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant