分页组件+Table表格+编程式导航

描述:

之前实现了自定义分页组件,但是由于现实业务需求(需要将过滤项表单、分页的offset和limit传递到路由中,即a?xxx=xxx&xxx=xxx)。因此对分页组件进行了重新的设计。

分页组件的重新设计

上一篇:Quasar的自定义分页组件

之前的分页组件主要是监听每页显示数量limit和偏移量offset的变化来触发事件,进行回调,在回调处发起网络请求。

由于上述需求,在新的分页组件中主要监听了页面改变的监听事件,并通过页面改变监听,触发编程式导航,从而改变页面路由,通过对页面路由的更新来发起网络请求,从而实现目标。






在父组件使用该分页组件时,只需要传入pagination即可,pagination是一个JSON对象,包含offset、limit、count。

在页面进行网络请求得到结果后,只需要改变pagination的内容,即可动态的更新分页组件。

分页组件 + table + 编程式导航的结合使用

描述:
在父组件使用Table表格和分页组件的过程中,一般还会存在过滤项表单,来对数据进行过滤请求,这些过滤项和分页的offset、limit都需要当作路由的query参数。

实际上,该query参数模样,相当于axios进行get请求时的params。因此将表单对应组件的v-model和请求所需的param定义成相同的名称。

期间遇到的问题:
基本上还是多次请求的问题,在编程式导航过程中,如果没有对应的更新分页组件,由于count的变化,容易让分页组件响应编程式导航,而且由于没有更新offset、limit,从而导致编程式导航成功响应,进行了二次网络请求。

最终的解决:
对原来的分页组件进行的更新。在每次获取网络请求结束后,动态的改变pagination中的count、limit、offset,从而基本触发了编程式导航,但是由于路由的query没有改变,而不会响应beforeRouteUpdate,也就不会再次响应网络请求。

实现过程

  • 首先,定义table。
// html

    ...
    //vue
    tableLoading: false, // 表格加载状态
    paginationControl: { rowsPerPage: 0 }, // 显示全部
    tableData: [],
    columns: [{
        name: 'severity',
        required: true,
        align: 'left',
        label: '问题级别',
        field: 'severity'
    },...
    ],
  • 其次,覆盖Table默认的分页,采用新的分页
// html

// vue
// table+分页组件所需
pagination: {
    offset: 0,
    limit: 12,
    count: 0
}
  • 此外,如果对过滤项进行点击过滤,是进行的编程式路由导航操作,将过滤项格式化成为规定的路由query格式(为了保证和get请求params一致)。
// vue methods中
filterSearch: function () {
    this.$router.push({
        path: this.$route.path,
        query: filterToQueryFormat(this.filterForm) // 将过滤项格式化匹配到路由
    })
}
// filterToQueryFormat,引用的utils。包含了
/**
 * 筛选项格式化到url
 * @param {{筛选项表单}} filterForm
 * @return {{返回url的query}} query
 */
export function filterToQueryFormat (filterForm) {
      console.log('filterToQuery')
      let query = {}
      for (var key in filterForm) {
        if (key.endsWith('__in')) {
          query[key] = filterForm[key].toString()
        } else {
          query[key] = filterForm[key] || filterForm[key] === '' ? filterForm[key] : null
        }
      }
      query.offset = 0
      console.log(filterForm)
      console.log(query)
      console.log('filterToQuery end')
      return query
}
/**
 * url格式化匹配筛选项
 * @param {{url的query}} query
 * @param {{筛选项表单}}} filterFrom 由于是对象的引用,所以在此对filterForm进行改变即改变了外层的filterForm
 * @return {{返回url的query}} query
 */
export function queryTofilterFormat (query, filterForm) {
      console.log('queryToFilter')
      let filter = {}
      for (var key in filterForm) {
        if (key.endsWith('__in')) {
          filter[key] = query[key] ? query[key].split(',') : []
        } else {
          filter[key] = query[key] ? query[key] : null
        }
      }
      filter.limit = query.limit
      filter.offset = query.offset
      console.log(query)
      console.log(filter)
      console.log('queryToFilter end')
      return filter
}
  • 接下来,将过滤项表单定义为filterFrom,表单项所对应的具体组件v-model根据网络请求param一一对应。
// html

q-btn color="secondary" size="sm" icon="search" label="筛选" @click="filterSearch" />
// vue
filterForm: { // 过滤项表单
    state__in: [],
    resolution__in: [],
    severity__in: [],
    is_tapdbug: null,
    file__icontains: null,
    author: null,
    ci_time__lte: null,
    ci_time__gte: null
}
  • 然后,每次进入页面,在mounted中进行第一次请求。对页面路由更新进行监听,从而发起请求。beforeRouteUpdate是只有页面路由的params或query进行改变才会触发,原页面复用,不进行页面刷新。
// vue
mounted () {
    // 加载数据
    this.tableRequest(this.$route.query)
 },
 beforeRouteUpdate (to, from, next) {
    // 路由query更新触发
    this.tableRequest(to.query)
    next()
  },
  • 最后,对数据请求的操作。
///
    /**
    * 表格数据请求
    * @param {{路由query参数}} query
    */
tableRequest: function (query) {
    this.tableLoading = true // 表格加载动画
    // 判断路由是否有limit和offset,如果没有,默认12、0
    query.limit = query.limit ? parseInt(query.limit) : 12
    query.offset = query.offset ? parseInt(query.offset) : 0
    issues(this.$route.params.project_id, query).then(response => {
    // 请求成功后,改变分页组件显示
    this.pagination = {
    limit: query.limit,
    offset: query.offset,
    count: response.count
    }
    // 将路由的query匹配到过滤项表单中
    this.filterForm = queryTofilterFormat(query, this.filterForm)
    // 返回数据
    this.tableData = response.results
    // 关闭table加载状态
    this.tableLoading = false
    }).catch(error => {
    this.tableLoading = false
    console.log(error)
    })
}

整个代码

// 分页组件




// issue_list






// utils
/**
 * 筛选项格式化到url
 * @param {{筛选项表单}} filterForm
 * @return {{返回url的query}} query
 */
export function filterToQueryFormat (filterForm) {
  console.log('filterToQuery')
  let query = {}
  for (var key in filterForm) {
    if (key.endsWith('__in')) {
      query[key] = filterForm[key].toString()
    } else {
      query[key] = filterForm[key] || filterForm[key] === '' ? filterForm[key] : null
    }
  }
  query.offset = 0
  console.log(filterForm)
  console.log(query)
  console.log('filterToQuery end')
  return query
}

/**
 * url格式化匹配筛选项
 * @param {{url的query}} query
 * @param {{筛选项表单}}} filterFrom 由于是对象的引用,所以在此对filterForm进行改变即改变了外层的filterForm
 * @return {{返回url的query}} query
 */
export function queryTofilterFormat (query, filterForm) {
  console.log('queryToFilter')
  let filter = {}
  for (var key in filterForm) {
    if (key.endsWith('__in')) {
      filter[key] = query[key] ? query[key].split(',') : []
    } else {
      filter[key] = query[key] ? query[key] : null
    }
  }
  filter.limit = query.limit
  filter.offset = query.offset
  console.log(query)
  console.log(filter)
  console.log('queryToFilter end')
  return filter
}

最后

代码感觉还是不够精简,虽然实现了一定的流程化,但是感觉还有其它改进过程,望指正。。

你可能感兴趣的:(分页组件+Table表格+编程式导航)