简介
一个不怎么高度自定义的移动端table
组件,可创建不定数量的列的table
(自己写着玩为了以后维护修改样式方便封装起来的
实现思路
- 表格头部一个循环:循环渲染每一列的列名
- 表格内容两重循环:外层循环渲染行,内层循环渲染每一行的每一列的内容
实现
环境:vue
+ vantui
,用van-row
+ van-col
模拟行和列
// 封装的table组件
<template>
<div class="fake-table">
<van-row class="fake-table__head">
<van-col class="col" v-for="(item, index) in headData" :key="index" :span="item.span">{{item.name}}</van-col>
</van-row>
<van-row class="fake-table__body" v-for="(item, index) in bodyData" :key="index">
<template v-for="(colItem, colIndex) in headData">
<van-col class="col" :span="colItem.span" :key="colIndex" v-if="colItem.prop">
<-- 这里其实重点只要关注v-model绑定的属性名。其他属性看项目具体需要,比如说placeholder也可以绑定:placeholder="item.placeholder"等等,只要传进来的数组符合数据结构就行 -->
<van-field v-model="item[colItem.prop]" placeholder="请输入名称" :disabled="item.editDisable" :class="[item.editDisable ? 'input-diabled': 'input-abled']"/>
</van-col>
<-- 这里是项目需要,不让事件冒泡,如果不需要可以去掉.stop修饰符。而capture就是用来捕获slot进来的元素的事件的,因为在父组件定义事件的话无法取到这里循环的colIndex -->
<van-col class="col" :span="colItem.span" :key="colIndex" @click.stop.capture="doThis($event, index)" v-else>
<slot></slot>
</van-col>
</template>
</van-row>
</div>
</template>
<script>
export default {
props: {
headData: {
type: Array,
default: () => []
},
bodyData: {
type: Array,
default: () => []
}
},
methods: {
doThis(e, rowIdx) {
if(e.target.id === 'edit') {
this.$emit('edit', rowIdx)
}
else if(e.target.id === 'delete') {
this.$emit('delete', rowIdx)
}
}
}
}
</script>
<style lang="less" scoped>
@inputPaddingLeft: 5px;
@colPaddingLeft: 10px;
.fake-table /deep/ .van-field__control {
padding-left: @inputPaddingLeft;
}
.col /deep/ .van-cell {
padding: 0;
}
.col /deep/ .input-diabled {
border: none;
}
.col /deep/ .input-abled {
border: 1px solid #DDDDDD;
}
.table-col {
height: 100%;
display: flex;
justify-content: flex-start;
align-items: flex-start;
font-family: PingFangSC-Medium, PingFang SC;
color: #313131;
}
.fake-table {
margin: 0 12px;
&__head, &__body {
border: 1px solid #DDDDDD;
&:not(:last-child) {
border-bottom: none;
}
}
&__head {
height: 40px;
background: #F5FAFF;
.col:extend(.table-col) {
font-size: 14px;
font-weight: 500;
line-height: 20px;
padding: @colPaddingLeft;
}
}
&__body {
.col:extend(.table-col) {
font-size: 13px;
font-weight: 400;
line-height: 18px;
padding: @colPaddingLeft @colPaddingLeft @colPaddingLeft calc(@colPaddingLeft - @inputPaddingLeft);
&:last-child {
padding-left: @inputPaddingLeft;
}
}
}
}
</style>
使用
// 父组件
// html
<fake-table :headData="tableHead" :bodyData="matirialUsed" @edit="editMatirial" @delete="deleteMatirial">
<template>
<van-icon id="edit" class="edit-btn" name="edit" size="14" color="#268AED" />
<van-icon id="delete" class="delete-btn" name="delete" size="14" color="#268AED" />
</template>
</fake-table>
// script
import fakeTable from '../../components/fake-table'
// ...省略一些代码
data {
return {
tableHead: [{
name: '材料名称', // 注意传进去的列名
span: '8',
prop: 'name' // 注意传进去的列属性名,要跟实际取得的数据的属性名一致,如matirialUsed数组的每一项的属性名
},
{
name: '型号',
span: '6',
prop: 'model'
},
{
name: '数量',
span: '5',
prop: 'num'
},
{
name: '操作',
span: '5',
prop: ''
}],
matirialUsed: [{
name: '',
model: '',
num: '0',
editDisable: true, // 是否可编辑
},
{
name: '',
model: '',
num: '0',
editDisable: true,
},
{
name: '',
model: '',
num: '0',
editDisable: true,
},
{
name: '',
model: '',
num: '0',
editDisable: true,
}]
}
},
components: {
fakeTable
},
methods: {
editMatirial(idx) {
let flag = this.matirialUsed[idx]['editDisable']
this.$set(this.matirialUsed[idx], 'editDisable', !flag)
},
deleteMatirial(idx) {
let temp = this.matirialUsed
temp.splice(idx, 1)
this.matirialUsed = temp
},
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。