Vue2封装一个表格,实现表头表体数据配置化

138 阅读1分钟

实现功能

  • 通过配置表头标题来实现表格渲染,原理,通过循环将表头数据和接口返回表体数据进行映射匹配,可以自定义表头宽度和内容

e42b4772a451b582f864d2569b14a8c.jpg

  • 封装一个tableList.vue组件
<template>
  <div class="abnormalList">
    <!-- 表头 -->
      <header class="abnormalTitle">
        <span v-for="item in listTitle" :key="item.key" :style="{'width': `${item.width}%`}">{{item.name}}</span>
      </header>
      <!-- 表体数据滚动 -->
      <vue-seamless-scroll
        class="wrap"
        :data="listData"
        :class-option="classOption"
      >
      <template v-if="listData.length>0">
          <div class="table-row" @click="handleClick(item)" v-for="(item, index) in listData" :key="Math.random() + index">
            <div class="table-column" :style="{'width': `${itemTitle.width}%`}" v-for="itemTitle in listTitle" :key="itemTitle.name">
            <!-- v-if="itemTitle['template']" 存在作用域插槽 -->
              <template v-if="itemTitle['template']">
                <!-- :name="itemTitle['template']" 作用域插槽名称 -->
                <!-- :cell="item[itemTitle['key']]" 拿到listData数据列表中  当前项   数据 -->
                <slot :name="itemTitle['template']" :cell="item[itemTitle['key']]">
                  {{item[itemTitle['key']]}}
                </slot>
              </template>
              <!-- 未设置插槽直接展示 -->
              <template v-else>
                {{item[itemTitle['key']]}}
              </template>
            </div>
          </div>
      </template>
      </vue-seamless-scroll>
      <div v-if="listData.length===0" class="empty-data">
        暂无数据
      </div>
    </div>
</template>

<script>
import VueSeamlessScroll from "vue-seamless-scroll";
export default {
  name: 'tableList',
  props: {
    clickFlag: {
      type: Boolean,
      default: false
    },
    listData: {
      type: Array,
      required: true,
      default() {
        return []
      }
    },
    listTitle: {
      type: Array,
      required: true,
      default() {
        return []
      }
    },
  },
  components: {
    VueSeamlessScroll
  },
  data() {
    return {
      // VueSeamlessScroll配置项
      classOption: {
        singleHeight: 36,
        limitMoveNum: 3,
      },
    }
  },
  created () {
  },
  methods: {
    // 当前行点击事件
    handleClick(item) {
      this.$emit('rowClick', item)
    }
  }
}
</script>

<style lang="less" scoped>
.empty-data {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.table-row {
  padding: 6px;
  display: flex;
  flex-wrap: nowrap;
  border-bottom: 1px solid rgba(110, 148, 187, 0.2);
  align-items: center;
  &.active {
    cursor: pointer;
  }
}
.table-column {
  display: inline-block;
  text-align: center;
}
.wrap {
  width: 100%;
  height: 80%;
  overflow: hidden;
}
.abnormalList {
  font-size: 14px;
  color: #52c0ff;
  height: 100%;
  .abnormalTitle {
    background: rgba(82, 192, 255, 0.25);
    display: flex;
    text-align: center;
    justify-content: center;
    align-items: center;
    padding-left: 10px;
    padding-right: 10px;
    height: 36px;
  }
}
</style>
  • 数据来源
// fuwu.js
export const fuwu = [{
  "evaluatePerson": "万水",
  "rateScore":"10分",
  "serveVisits": "yyy",
}, {
  "evaluatePerson": "徐权",
  "rateScore":"5分",
  "serveVisits": "海宁",
}, {
  "evaluatePerson": "桂发",
  "rateScore":"3分",
  "serveVisits": "桐乡",
}, {
  "evaluatePerson": "盛林",
  "rateScore":"20分",
  "serveVisits": "金陵",
}]
  • 父组件引用
<template>
  <table-list @rowClick="handlerowClick" :listData="listData" :listTitle="abnormalTitleList">
    <!-- 作用域插槽自定义cell单元格展示样式 -->
    <template v-slot:rankTemp="info">
      <div>
        <!-- 自定义前三名展示图片 -->
        <template v-if="imgSrcData[info.cell]">
          <img
            class="mingci"
            :src="imgSrcData[info.cell]"
            alt=""
          />
        </template>
        <template v-else>{{info.cell}}</template>
      </div>
    </template>
  </table-list>
</template>

<script>
import {fuwu} from './fuwu.js'
import tableList from "./tableList";
export default {
  name: "right-two.vue",
  data() {
    return {
      // 自定义单元格样式展示
      imgSrcData: {
        '1': require('@/assets/imgNew/first.png'),
        '2': require('@/assets/imgNew/second.png'),
        '3': require('@/assets/imgNew/three.png'),
      },
      listData: [], // 表格数据
      // 表头内容
      abnormalTitleList: [
        {
          name: '排名', // 表头
          key: 'rank', // 和接口数据返回key名称一致
          width: 10, // 百分比
          template: 'rankTemp', // 作用域插槽名称
        },
        {
          name: '护理员姓名',
          key: 'evaluatePerson',
          width: 25, // 百分比
        },
        {
          name: '任职机构',
          key: 'serveVisits',
          width: 30, // 百分比
        },
        {
          name: '评分',
          key: 'expTime',
          width: 25, // 百分比
        },
        {
          name: '',
          key: 'arrow',
          width: 10, // 百分比
        },
      ],
    };
  },
  mounted() {
    this.handleResData(fuwu) // mock接口返回数据
  },
  methods: {
    handlerowClick(item) {
      // 点击当前行do something
      console.log(item, 'ooo');
    },
    handleResData(data) {
      this.listData = data.map((item, index) => {
        return {
          ...item,
          rank: index + 1, // 添加排名
          arrow: '>', // 添加跳转图标
        }
      })

    },
  },
  components: {
    tableList
  },
};
</script>
<style lang="less" scoped>
.mingci {
  width: 18px;
  height: 18px;
}
</style>