table组件封装

使用用vue封装table组件,功能如下
1、是否显示表格的左右侧边框 border true|false(default);
2、 表格的对齐方式 align left(default) | right |center;
3、鼠标移动到每一行是否高亮 disabledHover true|false(default);
4、是否显示间隔斑马纹 stripe true|false(default);
5、是否显示表格正在加载中 loading true|false(default);
6、是否将表头固定 height 传入值表示将表头固定;
7、每行数据多选功能 checkbox选择功能
使用sass编写css,所以复用代码即npm i sass sass-loader。

<template>
  <div class="context" ref="container">
    <div
      :style="{height:height!=''&& height!=0?`${height}px`:'auto',overflow:'auto'}"
      class="container"
    >
      <table class="table" ref="table">
        <thead>
          <!-- 几行 几列-->
          <tr>
            <th width="50">
              <input type="checkbox" :checked="checked" @change="checkAll" ref="checkedSt" />
            </th>
            <th v-for="(item,i) in tableHeader" :key="item.key">{{item.name}}</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(value,i) in tableData" :key="i">
            <td>
              <input
                type="checkbox"
                :checked="checkedBool(value)"
                @change="iptChecked(value,$event)"
              />
            </td>
            <td v-for="(item,i) in tableHeader" :key="i">{{value[item.key]}}</td>
          </tr>
        </tbody>
      </table>
      <div class="loading" v-if="loading">
        <div v-show="spanShow">
          <span class="round"></span>
        </div>
      </div>
    </div>
    <!-- <button @click="handler">按钮</button> -->
  </div>
</template>

<script>
import { cloneDeep } from "lodash/cloneDeep";
export default {
  name: "hlTable",
  data() {
    return {
      checkBox: [],
      spanShow: false
    };
  },
  props: {
    tableData: {
      //表格数据
      type: Array,
      default: () => []
    },
    tableHeader: {
      //表格头
      type: Array,
      default: () => [],
      require: true
    },
    border: {
      //是否显示表格的左右侧边框
      type: Boolean,
      default: false
    },
    align: {
      //表格的对齐方式
      type: String,
      default: "left"
    },
    disabledHover: {
      //鼠标移动到每一行是否高亮
      type: Boolean,
      default: true
    },
    stripe: {
      //是否显示间隔斑马纹
      type: Boolean,
      default: false
    },
    loading: {
      //是否显示表格正在加载中
      type: Boolean,
      default: false
    },
    checkArr: {
      type: Array,
      default: () => []
    },
    height: {
      type: String,
      default: ""
    }
  },
  beforeMounted() {
    //浅拷贝不好
    // this.checkBox=[...this.checkArr];
    this.checkBox = cloneDeep(this.checkArr);
  },
  mounted() {
    this.init();
  },
  computed: {
    position() {
      if (this.align !== "left") {
        window.document.body.setAttribute("position", this.align);
      }
      return;
    },
    borderl() {
      if (this.border) {
        window.document.body.setAttribute("border", this.border);
      }
      return;
    },
    hover() {
      if (this.disabledHover) {
        window.document.body.setAttribute("hover", this.disabledHover);
      }
      return;
    },
    stripel() {
      if (this.stripe) {
        window.document.body.setAttribute("stripe", this.stripe);
      }
      return;
    },
    //全选框的状态
    checked() {
      return this.tableData.length === this.checkArr.length;
    }
  },
  watch: {
    checkBox() {
      if (this.checkBox.length !== this.tableData.length) {
        if (this.checkBox.length !== 0) {
          return (this.$refs.checkedSt.indeterminate = true);
        }
      }
      this.$refs.checkedSt.indeterminate = false;
    },
    loading: {
      immediate: true,
      handler: function() {
        console.log(this);
        if (this.loading) {
          var num = 0;

          this.timer = setInterval(() => {
            this.spanShow = true;
            num++;
            if (num === 3) {
              if (this.spanShow == true) {
                this.spanShow = false;
                num = 0;
              }
            }
            console.log(1);
          }, 1000);
        } else {
          console.log(2);
          clearInterval(this.timer);
        }
      }
    }
  },
  methods: {
    //初始化表格的样式
    init() {
      this.position;
      this.borderl;
      this.hover;
      this.stripel;
      if (this.height) {
        var table = this.$refs.table;
        var container = this.$refs.container;
        var cloneTable = table.cloneNode();
        container.style.paddingTop =
          table.children[0].getBoundingClientRect().height + "px";
        cloneTable.appendChild(table.children[0]);
        container.appendChild(cloneTable);
        cloneTable.classList.add("fixPosition");
      }
    },
    //点击每一行的选择框触发的函数。数据是单向数据流,不能直接修改父级的数据。
    iptChecked(value, e) {
      //如果已经选择的数据里有当前选择的数据则删除,如果没有则添加。
      var flag = this.checkBox.some(item => item.id === value.id);
      if (!flag) {
        this.checkBox.push(value);
      } else {
        var index = this.checkBox.findIndex(item => item.id === value.id);
        this.checkBox.splice(index, 1);
      }
      this.$emit("update:checkArr", this.checkBox);
    },
    //点击全选的函数
    checkAll() {
      if (this.checkBox.length === this.tableData.length) {
        this.checkBox = [];
      } else {
        this.checkBox = this.tableData;
      }
      this.$emit("update:checkArr", this.checkBox);
    },
    //每个选择框的状态
    checkedBool(value) {
      return this.checkBox.some(item => item.id === value.id);
    }
    // handler() {
    //   if (!this.isShow) {
    //     return this.isShow = true;
    //   } else {
    //     return this.isShow = false;
    //   }
    // }
  }
};
</script>

<style lang="scss" scoped>
body {
  text-align: left;
}
$table-boeder-color: #eee; //设置表格的border颜色
$tr-align-left: left; //设置tr的left对齐位置
$tr-align-center: center; //设置tr的center对齐位置
$tr-align-right: right; //设置tr的right对齐位置
//@mixin 后面的函数名称为自定义。
@mixin border($bool) {
  [border="true"] & {
    border-left: 1px solid $table-boeder-color;
    border-right: 1px solid $table-boeder-color;
  }
}
//设置tr的hover行为
@mixin hover($color) {
  &:hover {
    background: $color;
  }
  [hover="true"] & {
    &:hover {
      background: aliceblue;
    }
  }
}
//设置对齐方向
@mixin position($bool) {
  text-align: $bool;
  [position="right"] & {
    text-align: right;
  }
  [position="center"] & {
    text-align: center;
  }
}
//设置每行是否间隔行
@mixin stripe($bool) {
  background: $bool;
  [stripe="true"] & {
    &:nth-child(odd) {
      background: #5f87e0;
    }
  }
}
.context {
  height: 100%;
  position: relative;
  .fixPosition {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
  }
  .loading {
    height: 100%;
    width: 100%;
    position: absolute;
    top: 0;
    left: 0;
    text-align: center;
    background: #fff;
    opacity: 0.9;
    .round {
      display: inline-block;
      width: 0px;
      height: 0px;
      border-radius: 50%;
      background: cornflowerblue;
      opacity: 1;
      left: 50%;
      top: 50%;
      position: absolute;
      transform: translate(-50%, -50%);
      animation: change 5s;
      -moz-animation: change 5s;
      -webkit-animation: change 5s;
      -o-animation: change 5s;
      @keyframes change {
        from {
          width: 0px;
          height: 0px;
          opacity: 1;
        }
        to {
          width: 80px;
          height: 80px;
          opacity: 0;
        }
      }
    }
  }
  table {
    width: 100%;
    border-spacing: 0;
    font-size: 14px;
    background: #fff;
    @include border(false);
    thead {
      background-color: aliceblue;
    }
    th,
    td {
      border-bottom: 1px solid #eee;
      padding: 10px;
    }
    tr {
      @include hover("#fff");
      @include position(left);
    }
    tbody {
      tr {
        @include stripe("#fff");
      }
    }
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/Miss_hhl/article/details/104845631
今日推荐