之前用了一下vue-bootstrap,感覺里面的表格組件特別好用,但是如果僅僅為了使用表格就引入bootstrap,似乎有點不划算。所以自己就試着實現了一下bootstrap里面表格的部分功能,目前只是實現了表格內容的排版和列排序功能。后面再慢慢實現更多的功能吧,比如詳情框等等。
另外說一點點個人對bootstrap的使用感受吧,它的便捷是有目共睹的,能快速搭建好項目UI,排版也很優雅好看,但是不太適用於已定好UI設計稿的項目,因為它的布局是很靈活的,在排版上,尺寸大致能遵循設計稿,但是不能較真,如果非要和設計稿保持一致,排版尺寸還原精確到1個像素的話,bootstrap的便捷性就要大打折扣了,因為會有大量的樣式需要覆蓋。
效果如下:
父組件需傳遞的數據格式如下:
代碼如下:
<template>
<div class="d-table">
<ul class="listheader">
<li v-for="(it, key) in fields" :key="key">
<span
:class="{'up': sortField === key && sortrole > 0,'down': sortField === key && sortrole < 0}"
v-if="it.sort"
class='sort'
@click.capture="switchSort(key)"
><slot :name="key + '_H'" :data="{field: it, colum: key}">{{ $t(it.label) | cap }}</slot></span>
<span v-else><slot :name="key + '_H'" :data="{field: it, colum: key}">{{ $t(it.label) | cap }}</slot></span>
</li>
</ul>
<div class="listbody">
<div v-for="(it, i) in list" @click="rowClick(i, it)" :key="i">
<ul>
<li v-for="n in keys.length" :key="n">
<slot :name="keys[n-1]" :data="unitedata(i, it, n)">{{ it[keys[n-1]] }}</slot>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: () => ([])
},
fields: {
type: Object,
default: () => ({})
},
sortBy: {
type: String,
default: ''
}
},
data () {
return {
sortrole: 1,
sortField: this.sortBy,
detailshowIndex: -1
}
},
computed: {
keys () {
return Object.keys(this.fields)
},
list () {
const arr = this.items
if (this.sortField) {
const str = String(this.items[0][this.sortField]).charAt(0)
if (isNaN(str) && str !== '-' && str !== '+') {
arr.sort((x, y) => { // 當x[this.sortField]為對象時,未做判斷處理
return this.sortrole * x[this.sortField].localeCompare(y[this.sortField])
})
} else {
arr.sort((x, y) => {
return this.sortrole * (x[this.sortField] - y[this.sortField])
})
}
}
const len = arr.length
for (let i = 0; i < len; i++) {
arr[i].detailShowing = false
}
return arr
}
},
mounted () {
},
methods: {
rowClick (i, it) {
this.$emit('rowClick', i, it)
},
unitedata (index, item, n) { // params: 當前行數,當前行的數據包(Object), 當前行的列數
let obj = { index, item }
obj.field = this.fields[this.keys[n - 1]]
obj.value = item[this.keys[n - 1]]
return obj
},
switchSort (key) {
let ele = event.target
while (ele.parentNode.tagName !== 'LI') {
ele = ele.parentNode
}
if (ele.classList.value.indexOf('up') > -1) {
this.sortrole = -1
} else {
this.sortrole = 1
}
this.sortField = key
}
}
}
</script>
<style scoped lang="scss">
.d-table {
background-color: #fff;
padding: 10px 0;
.listheader {
border-bottom: 1px solid #b7b7b7;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
padding: 0 10px;
&>li {
font-weight: bold;
width: 16.5%;
overflow: hidden;
padding: 10px 0;
span.sort {
cursor: pointer;
position: relative;
&:before, &:after {
position: absolute;
right: -16px;
content: '';
display: inline-block;
border-right: 6px solid transparent;
border-left: 6px solid transparent;
}
&:before {
border-top: 6px solid #ababab;
top: 12px;
}
&:after {
border-bottom: 6px solid #ababab;
top: 5px;
}
&.down {
&:before {
border-top: 6px solid #21a185;
}
}
&.up {
&:after {
border-bottom: 6px solid #21a185;
}
}
}
}
}
.listbody {
&>div {
&:hover {
background-color: #f0f0f0;
}
&:first-child {
margin-top: 0;
}
ul {
padding: 0 10px;
display: flex;
justify-content: space-between;
li {
width: 16.5%;
overflow: hidden;
padding: 10px 0;
}
}
}
}
}
</style>
可能存在謬誤,歡迎指正,不勝感激!