elementui已經封裝好了 el-table 組件,只需要指定 data 數據源即可,因此通常在 vue 實例生命周期的 created 階段,從數據庫獲取數據,再將返回的數據綁定到 data
如果后端同學能直接返回前端需要展示的所有數據,那么前端只需要請求一次,多么的和諧,多么完美。
然而凡事皆有例外,比如在已有的table表格增加若干列,而數據從不同的源獲取,這時候再修改功能已經完善的接口顯然不明智,那么前端使用同步或異步請求來獲取數據是比較好的方案。
同步
例如一個文章接口只返回了文章id、作者、內容、創建時間等信息,而前端需要展示作者昵稱、簽名等,這些信息要從另一個接口獲取。
解決方式
- 獲取全部文章列表,保存到變量 list
- 對 list 的 author 字段去重后發起請求,此請求返回promise
- 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 = '-'
})
})
},
}
