为什么需要模型层(数据处理)

在 vue 的组件中,我们一般需要在 created 或者 mounted 中通过 api 来获取需要渲染到视图上的数据,或者在 methods 中获取数据,如果把这些逻辑都写在这里,会显得非常冗杂,如果把这部分 api 相关的抽离出来,单独封装,这样可以大大提升代码的可读性与可维护性。下面以 日志 这个业务逻辑来说明:

  1. <script>
  2. import log from 'lin/models/log' // 日志类的实例
  3. export default {
  4. async created() { // created钩子
  5. await this.initPage()
  6. },
  7. methods: {
  8. // 页面初始化
  9. async initPage() {
  10. try {
  11. this.users = await log.getLoggedUsers({}) // api请求
  12. const res = await log.getLogs({ page: 0 }) // api请求
  13. this.logs = res.collection
  14. } catch (err) {
  15. console.error(err)
  16. }
  17. },
  18. }
  19. }
  20. </script>

这里的 log 是日志类的实例,把所有跟日志相关的 api 封装在 Log 这个类中,这里就叫日志模型。在这个 Log 类中有很多相关日志获取的方法,如果有业务逻辑变动,只需要修改相关方法即可。我们把每个业务模型独立成一个 js 文件,声明一个类通过其属性和方法来实现这个模型相关的数据获取。

怎么来封装一个模型

我们来假设这样一个场景:有一个图书的后台管理系统,在图书管理这个模块,初始化的时候要看到已经上架的图书,点击图书可以看到详情,可以更改图书的上下架状态,可以删除图书。这其实是服务端典型的增删改查,我们既然采用前后端分离模式,这部分的处理就自然就是前端的职责了。

首先,当前这个业务模型是图书,那就可以创建一个 Book 类,管理员对图书的增加、删除、修改、查看这些行为分别对应类中的方法,这里已经有四个方法了。

  1. import { get, post, put, _delete } from '../utils/http'
  2. // 我们通过 class 这样的语法糖使模型这个概念更加具象化,其优点:耦合性低、可维护性。
  3. export default class Book {
  4. constructor() {}
  5. // 类中的方法可以代表一个用户行为
  6. async addBook(info) {
  7. const res = await post('v1/book', { info })
  8. return res
  9. }
  10. // 在这里通过 async await 语法糖让代码同步执行
  11. // 1. await 一定要搭配 async 来使用
  12. // 2. await 后面跟的是一个 Promise 对象
  13. async editBook(id) {
  14. const res = await put('v1/book', { id })
  15. return res
  16. }
  17. // static 方法修饰的成员不再属于某个对象,而是属于它所在的类。
  18. // 只需要通过其类名就可以访问,不需要再消耗资源反复创建对象。
  19. static async delectBook(id) {
  20. const res = await _delete(`v1/book/${id}`)
  21. return res
  22. }
  23. async getBooks() {
  24. const res = await get('v1/book')
  25. return res
  26. }
  27. }

小结

本小节主要还是介绍思想,将设计模式应用到前端代码中来,也是需要我们共同学习的,对于我们程序猿来说写代码是我们的工作,更是一种热爱,怎样让代码更加优雅更加有艺术感是一个长期话题,愿与君共勉。