vue+elementui搭建后台管理界面(8 同步/异步获取数据渲染table)

elementui已经封装好了 el-table 组件,只需要指定 data 数据源即可,因此通常在 vue 实例生命周期的 created 阶段,从数据库获取数据,再将返回的数据绑定到 data
如果后端同学能直接返回前端需要展示的所有数据,那么前端只需要请求一次,多么的和谐,多么完美。
然而凡事皆有例外,比如在已有的table表格增加若干列,而数据从不同的源获取,这时候再修改功能已经完善的接口显然不明智,那么前端使用同步或异步请求来获取数据是比较好的方案。

同步

例如一个文章接口只返回了文章id、作者、内容、创建时间等信息,而前端需要展示作者昵称、签名等,这些信息要从另一个接口获取。
解决方式

  1. 获取全部文章列表,保存到变量 list
  2. 对 list 的 author 字段去重后发起请求,此请求返回promise
  3. promise 链式调用完毕,将 list 绑定到 el-table组件

典型应用: 由promise 链式调用,当全部请求成功后再展示内容,任一步骤失败则请求的数据不完整,视为请求失败。

核心代码

<el-table 
  v-loading="listLoading"
  :data="list"
  border
  fit
>
<el-table-column label="昵称"
                min-width="100"
                align="center">
<template slot-scope="scope">
    <span v-if="userInfo[scope.row.author]">{{ userInfo[scope.row.author].nickname }}</span>
    <span v-else> - </span>
</template>
</el-table-column>
created() {
  this.getList()
},
methods: {
  getList() {
    // 先获取帖子信息,再根据帖子信息查找用户信息和帖子详情
    this.listLoading = true // 很重要,在所有数据返回前,页面要一直显示 loading
    let list = []
    let total = 0
    getArticleListApi(this.listQuery)
    .then(response => {
      list = response.data.items
      total = response.data.total
      return this.getAuthorInfo(list)
    })
    .then(() => {
      this.list = list
      this.total = total
      // 这里成功获取了作者信息, loading 结束
      this.listLoading = false
    })
    .catch(err => {
      this.listLoading = false
      if(err === 'CANCELD_BY_USER'){
        return
      }
      FetchDataNotifyWarning(err, 3)
    })
  },
  // 获取用户信息
  getAuthorInfo(list){
    // 根据用户ID获取昵称、个性签名、帐号状态等信息
    const _this = this
    let users = new Set(list.map(v => v.author))
    let promises = []
    function promiseFunc(id){
      return new Promise((resolve, reject) => {
        getAccountInfoApi(id)
        .then(resp => {
          _this.userInfo[id] = resp.data.data
          resolve()
          })
        .catch(err => {
          // 忽略可能获取不到用户的错误
          resolve()
        })
      })
    }
    users.forEach(id => {
      if(id){
        promises.push(promiseFunc(id))
      }
    })
    return Promise.all(promises)
  },
}

异步

典型应用: 先展示所有文章信息,每一行增加一个镜像字段,如: _async_label ,请求成功后更新该字段内容,失败则更新为特定字符,如 '-' 。

核心代码

<el-table-column label="标签"
                min-width="100"
                align="center">
<template slot-scope="scope">
    <span>{{ scope.row._async_label }}</span>
</template>
</el-table-column>
methods: {
  getList() {
    this.listLoading = true
    this.fetchData(this.listQuery)
    .then(response => {
      let tablist = response.data.items
      let total = response.data.total
      // 异步显示文章标签
      tablist.forEach(item => {
        item._async_label = ''
      })
      this.list = tablist
      this.total = total
      this.getLabel()
      // 这里 loading 结束,页面上可以看到表格了
      this.listLoading = false
    })
    .catch(err => {
      this.$notify.warning({
        message: err || '未获取到相关信息,请刷新页面或稍候再试',
        duration: 3 * 1000,
      })
      this.listLoading = false
    })
  },
  // 获取 文章标签
  getLabel(){
    this.list.forEach(item => {
      getArticleLabelApi(item.articleId)
      .then(resp => {
        item._async_label = resp.data.val
      })
      .catch(()=>{
        item._async_label = '-'
      })
    })
  },
}
posted @ 2019-01-30 15:12  葡萄不吐皮  阅读(9605)  评论(0编辑  收藏  举报