vue 列表 mixin

后台项目做多了就会发现,在一个成熟的后台项目中,列表页面的结构以及逻辑都是相对固定的,怎样才能把重复的这部分提取出来呢

哪些需要提取

项目里用的 UI 库是 Element UI 。一个列表页从 UI 表现来看上至下通常包含这么几部分:筛选栏,列表,分页。在 vue 单文件组件中看的话,主要是模板区和 js 区,项目里列表页一般是统一风格,所以公共样式不会写在列表组件里。首先模板部分我认为是不需要提取出来的,一方面是因为用了 element 表格组件,二次封装会使传值等变的更为复杂,另一方面是封装过后在可读性上有很大的损失

怎么封装

由于只提取了公共的逻辑,模板部分未有提取,而且每个列表页调用的 api 也不同,选择采用 mixin 的方式,在 mixin 中定义公共的数据变量以及方法,在对应的业务单文件组件中引入。mixin 的特性可以在 官方文档 中了解,通过这种方式优点是可以提取公共逻辑,并且可以在混入的地方通过新声明覆盖旧声明的方式重写;缺点是通过 mixin 引入的内容在业务页面是没法直接看到的,这也是使用 mixin 的主要问题。在项目的协作开发,我们采用约定开发的方式,使用者要了解页面所使用的 mixin ,这样可以降低使用 mixin 导致出问题的几率

成果

/**
 * list.js 列表 mixin
*/

import { TIMER_DURATION } from '@/config'

export default {
  data () {
    return {
      // 接口的 api 方法
      getListApi: () => {},
      // 请求参数
      reqParams: {},
      // 过滤参数
      filterParams: {},
      // 列表数据
      list: [],
      // 分页数据
      page: {
        pageStart: 1,
        pageSize: 20
      },
      // 返回参对应列表数据的字段名
      responseListName: 'list',
      // 请求接口 loading flag
      listLoading: false,
      // 是否开启轮询
      needPolling: false,
      // 轮询的时间间隔,默认采用全局统一间隔时间
      timerDuration: TIMER_DURATION,
      // 轮询定义的定时器
      timer: null
    }
  },
  mounted () {
    // 方法调用放在页面中
    // this.getList()
    // this.startPolling()
  },
  beforeDestroy () {
    this.endPolling()
  },
  methods: {
    getList () {
      if (!this.listLoading) {
        this.listLoading = true
        this.getListApi({
          ...this.reqParams,
          ...this.filterParams,
          ...this.page
        }).then(res => {
          // 翻页可能连续点击,如果返回数据不是当前页,不执行赋值操作
          if (res.data && res.data.page && (this.page.pageStart !== res.data.page.pageStart)) {
            return
          }
          this.handleGetListResponse(res)
        }).catch(() => {
          this.handleGetListErr()
        }).finally(() => {
          this.listLoading = false
        })
      }
    },

    // 如果默认方法不能满足需求,可以在组件中重写这个方法来处理返回数据
    handleGetListResponse (res) {
      res.data = res.data || {}
      this.list = res.data[this.responseListName] || []
      res.data.page && (this.page = res.data.page)
    },

    handleGetListErr () {},

    // 翻页
    handleSizeChange (val) {
      this.page.pageStart = val
      this.getList()
    },

    // 过滤
    handFilterStatusChange (e) {
      // 结束当前的定时任务,避免和本次请求冲突
      this.endPolling()
      this.getList()
      this.startPolling()
    },

    // 开始轮询
    startPolling () {
      if (!this.needPolling) {
        return
      }
      this.timer = setInterval(this.getList, this.timerDuration)
    },
    // 结束轮询
    endPolling () {
      if (!this.needPolling) {
        return
      }
      clearInterval(this.timer)
    }
  }
}
/**
* 页面中引入 mixin 使用
*/




上述示例是稍复杂的应用,若只是展示列表,只需重置 data 中的数据即可

总结

通过这样的方式,将同类业务中相同的逻辑抽离出来,列表页面的逻辑被简化,后续的业务迭代中只需很少的代码即可实现需求,公共的逻辑在 mixin 中统一维护,提高开发效率

你可能感兴趣的:(vue 列表 mixin)