vue的table表格组件的封装方式

 更新时间:2023年06月09日 08:57:48   作者:maxiaoxin1314  
这篇文章主要介绍了vue的table表格组件的封装方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

vue table表格组件的封装

封装的vue表格组件,整理记录下

1,分为两个组件去封装,一个是基本的表格的框架组件,一个是行内容组件

基本的表格框架组件:

增加了移动调整列大小功能

<template>
  <div class="data-table">
    <!-- 表格标题 -->
    <table>
      <thead>
        <tr ref="dataTableHead">
          <th v-if="isCheck">
            <input type="checkbox" class="text-input" v-model="isAll" />
          </th>
          <th v-if="isNum">{{ $t("common.num") }}</th>
          <slot name="data-table-head"></slot>
          <th></th>
        </tr>
      </thead>
    </table>
    <div class="table-content">
      <!-- 表格数据内容 -->
      <table v-show="tableData.length > 0 && !isLoading">
        <tbody ref="dataTableContent">
          <slot name="data-table-content"></slot>
          <!-- <data-table-row :idx="idx" :item="item" v-for="(item, idx) in tableData" :key="idx"></data-table-row> -->
        </tbody>
      </table>
      <!-- 暂无数据 -->
      <div class="table-nodata" v-show="tableData.length == 0 && !isLoading">{{ $t("common.nodata") }}</div>
      <div class="table-loading" v-show="isLoading">{{ $t("common.loading") }}</div>
    </div>
  </div>
</template>
<script>
export default {
  name: "DataTableComp",
  props: {
    tableData: {
      //表格数据
      type: Array,
      default: () => [],
    },
    isLoading: {
      //是否正在加载数据
      type: Boolean,
      default: false,
    },
    isCheck: {
      type: Boolean,
      default: false,
    },
    isNum: {
      type: Boolean,
      default: false,
    },
    selects: {
      type: Array,
      default: () => [],
    },
  },
  provide() {
    return { dataTable: this };
  },
  data: () => ({
    isAll: false,
    selectList: [],
    isLoad: false,
  }),
  watch: {
    selectList: {
      //多选表格,选中的数据项索引数组
      deep: true,
      handler() {
        if (!this.isLoad) {
          this.$emit("update:selects", this.selectList);
          this.$emit("table-select", this.selectList);
        }
      },
    },
    selects() {
      //多选表格,选中的数据项
      this.isLoad = true;
      this.selectList = this.selects;
      var that = this;
      this.$nextTick(function() {
        that.isLoad = false;
      });
    },
    isAll() {
      //是否全选多选表格
      if (this.isAll) {
        var list = [];
        for (var i = 0; i < this.tableData.length; i++) {
          list.push(i);
        }
        this.selectList = list;
      } else {
        this.selectList = [];
      }
    },
    tableData() {
      //表格数据更新,重新渲染
      this.isLoad = true;
      var that = this;
      this.$nextTick(function() {
        that.initColumWidth();
        that.isLoad = false;
      });
    },
  },
  methods: {
    clearSelect() {
      //多选表格,清空选中
      this.isAll = false;
    },
    listenEvent() {
      this.app.$on("table-select-clear", this.clearSelect);
    },
    offEvent() {
      this.app.$off("table-select-clear", this.clearSelect);
    },
    initColumWidth() {
      //初始每列的宽度,保留每次调整后的列宽
      if (this.$refs.dataTableContent && this.$refs.dataTableHead) {
        if (this.tableData.length > 0 && !this.isLoading) {
          var head = this.$refs.dataTableHead;
          var body = this.$refs.dataTableContent;
          if (body.children) {
            for (var i = 0; i < body.children.length; i++) {
              for (var j = 0; j < head.children.length - 1; j++) {
                var td = body.children[i].children[j];
                td.style.width = head.children[j].style.width;
              }
            }
          }
        }
      }
    },
    //移动调整列大小
    onTableColum() {
      var movepage = document.getElementById("moving_page");
      if (this.$refs.dataTableContent && this.$refs.dataTableHead) {
        var dataTableContent = this.$refs.dataTableContent;
        this.$refs.dataTableHead.onmousedown = function(e) {
          if (e.target.tagName == "TH" && e.target != this.lastElementChild) {
            var elmt = e.target;
            var startX = e.pageX;
            var distance = e.pageX - elmt.offsetLeft;
            var leftRight = distance < elmt.offsetWidth * 0.5 ? "left" : "right";
            var elmt1 = leftRight == "left" ? elmt.previousElementSibling : elmt.nextElementSibling;
            if (elmt1 != this.lastElementChild) {
              var width = elmt.offsetWidth;
              var width1 = elmt1.offsetWidth;
              movepage.style.display = "flex";
              movepage.style.cursor = "ew-resize";
              movepage.onmousemove = function(e) {
                var w = e.pageX - startX + width;
                var w1 = width + width1 - w;
                elmt.style.width = w + "px";
                elmt1.style.width = w1 + "px";
                for (var i = 0; i < dataTableContent.children.length; i++) {
                  var td = dataTableContent.children[i].children[elmt.cellIndex];
                  var td1 = leftRight == "left" ? td.previousElementSibling : td.nextElementSibling;
                  td.style.width = w + "px";
                  td1.style.width = w1 + "px";
                }
              };
              movepage.onmouseup = function() {
                movepage.onmousemove = null;
                movepage.style.display = "none";
              };
            }
          }
          e.preventDefault();
        };
      }
    },
  },
  mounted() {
    this.listenEvent();
    this.onTableColum();
  },
  beforeDestroy() {
    this.offEvent();
  },
};
</script>
<style lang='scss'>
.data-table {
  display: block;
  overflow-x: hidden;
  overflow-y: hidden;
  padding-bottom: 0.1rem;
  height: 100%;
  width: 100%;
  table {
    background: white;
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
    thead > tr {
      background: #cedeee;
      border-radius: 0.4rem;
      line-height: 3rem;
      white-space: nowrap;
      height: 3rem;
      display: flex;
      flex-direction: row;
      cursor: ew-resize;
    }
    thead > tr > th {
      text-align: center;
      font-size: 1.4rem;
      font-weight: normal;
    }
    thead > tr > th:not(:last-child) {
      // border-right: solid 1px  #0095ec;
      min-width: 5rem;
    }
    thead > tr > th:last-child {
      width: 0.8rem;
    }
    tbody > tr {
      display: flex;
      flex-direction: row;
      border-radius: 0.4rem;
      align-items: center;
      line-height: 1.6rem;
      min-height: 3rem;
    }
    tbody > tr:nth-child(even) {
      background: #f3f3f3;
    }
    tbody > tr:hover,
    tbody > tr.active {
      color: #388dea;
      background-color: #d9edf6;
    }
    tbody > tr.active {
      font-weight: bold;
    }
    tbody > tr > td {
      text-align: center;
      font-size: 1.2rem;
      min-width: 4rem;
      word-break: break-word;
      white-space: normal;
      > span {
        max-width: 100%;
        white-space: normal;
        word-break: break-word;
      }
      a {
        color: #0095ec;
        text-decoration: underline;
        font-size: 1.2rem;
        cursor: pointer;
      }
      button:nth-child(odd),
      button.btn-white {
        @extend .btn-white;
        height: 2.4rem !important;
        line-height: 2.4rem !important;
      }
      button:nth-child(even),
      button.btn-orange {
        @extend .btn-orange;
        height: 2.4rem !important;
        line-height: 2.4rem !important;
      }
      a:not(:last-child),
      button:not(:last-child) {
        margin-right: 0.8rem;
      }
    }
  }
  .table-content {
    height: calc(100% - 3.1rem);
    overflow-y: auto;
    overflow-x: hidden;
    border: dashed 0.1rem gainsboro;
    border-top: none;
    .table-nodata {
      font-weight: bold;
      margin: 0.8rem;
      font-size: 1.2rem;
      border: #e2a814 0.1rem dashed;
      background-color: #f6f0ca;
      display: flex;
      align-items: center;
      justify-content: center;
      height: calc(100% - 1.8rem);
      color: black;
    }
    .table-loading {
      @extend .table-nodata;
      color: red;
      font-size: 1.4rem;
    }
  }
}
</style>

行内容组件:

<template>
  <tr>
    <td v-if="dataTable.isCheck">
      <input type="checkbox" class="text-input" v-model="dataTable.selectList" :value="idx" />
    </td>
    <td v-if="dataTable.isNum">{{idx+1}}</td>
    <slot />
  </tr>
</template>
<script>
export default {
  name: "DataTableRow",
  props: {
    idx: {
      type: Number,
      default: 0
    },
    item: {
      type: Object,
      default: () => { }
    }
  },
  inject: ["dataTable"],
  provide () {
    return { dataTableRow: this };
  }
};
</script>
<style>
</style>

2,main.js中全局定义使用:

import DataTableComp from "@/components/comp/table/DataTableComp";
import DataTableRow from "@/components/comp/table/DataTableRow";
Vue.use({
  install: function() {
    Vue.component("data-table", DataTableComp); //数据表格组件
    Vue.component("data-table-row", DataTableRow); //数据表格行组件
  },
});

3,在组件中使用

<data-table :is-num="false" :table-data="dataList" :is-check="true" :is-custom="true" :selects.sync="selectList">
          <template slot="data-table-head">
            <th style="width:15rem">{{ $t("common.name") }}</th>
            <th style="width:12rem">{{ $t("common.age") }}</th>
            <th style="width:12rem">{{ $t("common.company") }}</th>
          </template>
          <template slot="data-table-content">
            <data-table-row v-for="(item, idx) in dataList" :key="'abc' + idx" :idx="idx" :item="item">
              <td style="width:15rem">{{ item.name}}</td>
              <td style="width:12rem">{{ item.age}}</td>
              <td style="width:12rem">{{ item.company}}</td>
            </data-table-row>
          </template>
        </data-table>

is-num是否显示行的序号,is-check是否可以选中,select.sync是选中的行数的序号

vue封装table组件---万能表格

组件table.js

先看效果图

万能哦

搜索条件-按钮都有的哦!拿来即用,不用谢,哈哈

<!-- pro-table.vue -->
<template>
  <div class="new-table">
    <!-- 搜索框 -->
    <div v-if="searchLength > 0" :class="tableType === '2' ? 'input-boxs' : 'input-boxs2'">
      <div style="display: flex;justify-content: space-between;flex-wrap: wrap;">
        <div class="ycl custom-row">
          <div v-for="(slot, index) in slotList" :key="`custom-search-${index}`" class="col-pd" v-bind="searchFit">
            <slot :name="index" />
          </div>
          <div v-for="field in searchFields" :key="field.key" v-bind="searchFit" class="col-pd">
            <el-input
              v-if="field.type === 'Input'"
              :key="field.key"
              v-model="search[field.key]"
              v-bind="field.props"
              :clearable="searchLength < 2"
              @clear="initializeParams"
            />
            <el-select
              v-else-if="field.type === 'Select'"
              :key="field.key + 1"
              v-model="search[field.key]"
              style="width: 100%;margin-bottom: 5px;"
              v-bind="field.props"
            >
              <el-option
                v-for="option in field.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
            <el-datePicker
              v-else-if="field.type === 'Date'"
              :key="field.key + 2"
              v-model="search[field.key]"
              :type="field.dateType || 'date'"
              v-bind="field.props"
              style="display: block"
            />
            <el-cascader
              v-else-if="field.type === 'Cascader'"
              v-model="search[field.key]"
              v-bind="field.props"
              :data="field.options"
            />
          </div>
          <div class="col-pd">
            <!-- 搜索重置按钮 -->
            <el-button type="primary" style="margin-right: 8px" @click="searchHandle">查询</el-button>
            <el-button v-if="searchLength > 1" type="primary" plain @click="initializeParams">重置</el-button>
          </div>
        </div>
        <div v-if="Object.keys(buttonList).length > 0" class="ycr custom-row">
          <slot v-if="Object.keys(buttonList).length > 0" />
        </div>
      </div>
    </div>
    <!-- 按钮 -->
    <div :class="tableType === '2' ? 'table-content-boxs' : 'table-content-boxs2'">
      <el-table
        ref="table"
        class="iview-table"
        style="width: 100%;"
        :height="height"
        :data="rows"
        :span-method="spanMethod"
        v-bind="tableProps"
        @sort-change="(column, key, order) => emitEventHandler('on-sort-change', column, key, order)"
        @selection-change="selection => emitEventHandler('on-selection-change', selection)"
        @select-all-cancel="selection => emitEventHandler('on-select-all-cancel', selection)"
        @select-all="selection => emitEventHandler('on-select-all', selection)"
        @select-cancel="(selection, row) => emitEventHandler('on-select-cancel', selection, row)"
        @select="(selection, row) => emitEventHandler('on-select', selection, row)"
        @current-change="
          (currentRow, oldCurrentRow) =>
            (tableConfig['highlight-row'] || tableConfig['highlightRow']) &&
            emitEventHandler('on-current-change', currentRow, oldCurrentRow)
        "
      >
        <!--表格第一列-->
        <el-table-column
          v-if="columns.length>0 && columns[0].type"
          :label="columns[0].title"
          :type="columns[0].type"
          :width="columns[0].width"
          :min-width="columns[0].minWidth"
        />
        <!--表格其它列-->
        <el-table-column
          v-for="(value,index) in columnAll"
          :key="index"
          :prop="value.key"
          :label="value.title"
          :min-width="value.minWidth"
          :width="value.width"
          show-overflow-tooltip
        >
          <template slot-scope="scope">
            <template v-if="!value.render">
              <template v-if="value.formatter">
                {{ value.formatter(scope.row, value) }}
              </template>
              <template v-else-if="value.getImgurl">
                <el-image
                  :src="value.getImgurl(scope.row, value)"
                  style="width: 70px; height: 70px"
                  :preview-src-list="value.previewSrcList ? value.previewSrcList(scope.row, value) : value.getImgurl(scope.row, value).split(',')"
                />
              </template>
              <template v-else>
                {{ scope.row[value.key] }}
              </template>
            </template>
            <!--扩展dom-->
            <template v-else>
              <Table :key="`cus${index}`" :render="value.render" :param="scope" />
            </template>
          </template>
        </el-table-column>
      </el-table>
      <!--分页插件-->
      <div v-show="rows.length" class="page">
        <el-pagination
          v-if="pagination"
          :current-page="pageNumber"
          :page-sizes="[10, 20, 30, 40]"
          :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="pageSize => (page = { pageNumber: 1, pageSize })"
          @current-change="pageNumber => (page = emitDataHandle({ pageNumber }))"
        />
      </div>
    </div>
  </div>
</template>
<script>
// render函数
import Table from './components/table'
export default {
  name: 'NTable',
  components: { Table },
  props: {
    tableType: {
      type: String,
      default: '1' // 1: has-card (table表格被card包裹)  2:no-card (table表格没有被table包裹)
    },
    columns: {
      type: [Array, Object],
      required: true
    },
    data: {
      type: [Array, Object],
      required: true
    },
    rowsField: {
      type: String,
      default: 'records'
    },
    width: {
      type: String || Number,
      default: 'auto'
    },
    height: {
      type: [String, Number],
      default: 'auto'
    },
    totalField: {
      type: String,
      default: 'total'
    },
    pageNumberField: {
      type: String,
      default: 'current'
    },
    spanMethod: {
      type: Object,
      default: () => {}
    },
    // 响应式
    searchFit: {
      type: Object,
      default: () => {
        return {
          xs: 24,
          sm: 12,
          md: 6,
          lg: 4
        }
      }
    },
    // 分页
    pagination: {
      type: [Boolean, Object],
      default: false
    },
    // 表格配置项
    tableConfig: {
      type: Object,
      default: () => {}
    },
    extendSearchFields: {
      type: Array,
      default: () => []
    },
    // 快速跳转至某一页
    showElevator: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      page: {
        pageNumber: 1,
        pageSize: 10
      },
      search: {},
      searchFields: [],
      slotsList: [],
      isFullscreen: false
    }
  },
  computed: {
    rows() {
      return this.data[this.rowsField] || []
    },
    columnAll () {
      const arr = []
      this.columns.map(item => {
        if (!item.type) {
          arr.push(item)
        }
      })
      return arr
    },
    total() {
      return this.data[this.totalField] || 0
    },
    pageTotal() {
      return this.data.pages || 0
    },
    pageNumber() {
      return this.data[this.pageNumberField] || this.page.pageNumber || 1
    },
    pageSize() {
      return this.page.pageSize || 10
    },
    // 表格配置
    tableProps() {
      const defatult = {
        stripe: true
      }
      return this.tableConfig && this.isObject(this.tableConfig) && Object.keys(this.tableConfig).length
        ? { ...defatult, ...this.tableConfig }
        : defatult
    },
    // 分页配置
    pageProps() {
      const defatult = {
        // size: 'small',
        showTotal: false,
        showElevator: false,
        showSizer: true
      }
      return this.pagination && this.isObject(this.pagination) && Object.keys(this.pagination).length
        ? { ...defatult, ...this.pagination }
        : defatult
    },
    // 联合搜索的字段
    isShowSelectInput() {
      // eslint-disable-next-line no-irregular-whitespace
      return this.columns.some(item => item.search && item.search.type === 'SelectInput') || false
    },
    slotList() {
      const result = {}
      for (const key in this.$slots) {
        if (key.indexOf('custom-search') !== -1) {
          result[key] = this.$slots[key]
        }
      }
      return result
    },
    buttonList() {
      const result = {}
      for (const key in this.$slots) {
        if (key.indexOf('default') !== -1) {
          result[key] = this.$slots[key]
        }
      }
      return result
    },
    // 搜索框的数量
    searchLength() {
      return Object.keys(this.slotList).length + this.searchFields.length
    }
  },
  watch: {
    // 监听 分页变化
    page() {
      this.$emit('on-change', this.emitDataHandle())
    },
    // 监听 配置项变化
    extendSearchFields() {
      this.initialize()
    }
  },
  created() {
    this.initialize()
  },
  mounted() {
    this.$emit('on-table-mounted', this.$refs.table)
  },
  methods: {
    // 事件触发器
    emitEventHandler(event, ...args) {
      this.$emit(event, ...args)
    },
    emitDataHandle(params = {}) {
      return this.Object2NotNull({
        ...this.page,
        ...this.search,
        ...params
      })
    },
    // 刷新表格
    refresh() {
      this.emitEventHandler('on-refresh', this.emitDataHandle())
    },
    resetParams() {
      Object.keys(this.search).forEach(k => (this.search[k] = null))
      return this.emitDataHandle({ pageNumber: 1, pageSize: 10 })
    },
    searchHandle() {
      this.page.pageNumber = 1
      this.emitEventHandler('on-search', this.emitDataHandle())
    },
    initializeParams() {
      this.page.pageNumber = 1
      Object.keys(this.search).forEach(k => (this.search[k] = null))
      if (this.page.pageNumber === 1) {
        this.$emit('on-reset', this.emitDataHandle({ pageNumber: 1, pageSize: 10 }))
      }
    },
    isObject(value) {
      const type = typeof value
      return value != null && (type === 'object' || type === 'function')
    },
    /**
     * @param {*} obj 对象
     * @description *
     * 处理对象参数值,排除对象参数值为”“、null、undefined,并返回一个新对象
     */
    Object2NotNull(obj) {
      const param = {}
      if (obj === null || obj === undefined || obj === '') return param
      for (var key in obj) {
        if (Object.prototype.toString.call(obj[key]).slice(8, -1) === 'Object') {
          param[key] = this.Object2NotNull(obj[key])
        } else if (
          obj[key] !== null &&
          obj[key] !== undefined
          //  obj[key] !== ''
        ) {
          param[key] = obj[key]
        }
      }
      return param
    },
    getSearchFields() {
      // return new Promise((resolve, reject) => {})
      const temp = []
      // 合并额外字段
      const _columns = this.columns.filter(
        // eslint-disable-next-line no-prototype-builtins
        item => item.search && item.search.hasOwnProperty('type') && item.search.type !== 'SelectInput'
      )
      const searchFields = [..._columns, ...this.extendSearchFields]
      searchFields.forEach(async (item, index) => {
        const { search } = item
        // eslint-disable-next-line no-prototype-builtins
        if (search && search.hasOwnProperty('type')) {
          const o = {
            title: item.title,
            key: item.key,
            type: search.type,
            sort: search.sort || index
          }
          // eslint-disable-next-line no-prototype-builtins
          if (search.hasOwnProperty('props')) {
            o.props = search.props
          }
          if (search.type === 'Select' || search.type === 'Cascader') {
            let _options = null
            if (Array.isArray(search.options)) {
              _options = search.options
            } else if (typeof search.options === 'function') {
              const res = await search.options(...(search.params || []))
              if (search.format && typeof search.format === 'function') {
                _options = search.format.call(this, res)
              } else {
                _options = res
              }
            }
            o.options = _options
          }
          if (search.type === 'Date') {
            o.dateType = search.dateType
          }
          this.$set(this.search, item.key, search.type === 'Cascader' ? [] : null)
          temp.push(o)
        }
      })
      this.searchFields = temp.sort((a, b) => a.sort - b.sort)
    },
    initialize() {
      // 获取需要查询的字段
      this.getSearchFields()
      // 初始化查询字段
      // this.initializeParams()
    }
  }
}
</script>
<style lang="scss">
  .new-table {
    .custom-row {
      display: flex;
      flex-wrap: wrap;
      // margin: 10px 0;
      > button {
        margin-right: 5px !important;
      }
    }
    .custom-append {
      display: flex;
      > div :not(:last-child) {
        // margin-right: 15px !important;
      }
      .custom-clild {
        margin-right: 15px !important;
        > div :not(:last-child) {
          // margin-right: 5px !important;
          margin-top: 1px;
        }
      }
    }
    .custom-search {
      display: flex;
    }
    .page {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      font-size: 13px;
      font-family: Microsoft YaHei;
      font-weight: 400;
      color: rgba(144, 147, 153, 1);
      margin-top: 20px;
    }
    .ycIpage {
      .ivu-page-item-jump-next,
      .ivu-page-item-jump-prev,
      .ivu-page-next,
      .ivu-page-item,
      .ivu-page-prev {
        border: none !important;
      }
      .ivu-page-item {
        color: rgb(48, 49, 51);
        font-weight: bold;
      }
      .ivu-page-item-active {
        color: rgb(24, 144, 255);
      }
    }
    .ivu-table-wrapper {
      margin-bottom: 32px;
    }
    .ivu-table::before {
      height: 0 !important;
    }
    .ivu-input-group-prepend,
    .ivu-input-group-append {
      background: #fff;
    }
    .ivu-input-group-append .ivu-btn {
      i {
        font-size: 16px;
        position: relative;
        right: 8px;
      }
    }
    .no-data-text {
      display: block;
      margin-left: 10px;
      font-size: 16px;
      margin: 100px;
      opacity: 0.8;
      .iconfont {
        font-size: 140px;
        color: #e2e5eb;
      }
    }
    .input-boxs {
      padding: 12px 10px 12px 10px;
      margin-bottom: 8px;
      background-color: #fff;
      border-radius: 2px;
    }
    .input-boxs2 {
      margin-bottom: 14px;
      // margin-top: 11px;
    }
    .table-content-boxs {
      padding: 0 10px 6px;
      background-color: #fff;
      border-radius: 2px;
    }
    .table-content-boxs {
      padding-top: 10px;
    }
    .table-content-boxs2 {
      margin-top: 10px;
    }
    .iview-table {
      margin-top: 10px;
    }
    .no-button-text {
      font-size: 15px;
      font-weight: 700;
    }
    .func-icon-btn {
      font-size: 18px;
      font-weight: bold;
      margin-left: 5px;
    }
    .col-pd {
      // padding: 0;
      margin-right: 10px;
    }
  }
</style>
<style lang="scss" scoped>
  ::v-deep .el-row--flex {
    margin-top: 0px !important;
    height: 36px;
  }
  ::v-deep .el-table::before{
        height: 0 !important;
  }
  ::v-deep .el-table td{
    padding: 12px 0 !important;
    height: 23px !important;
    line-height: 23px !important;
  }
  .new-table {
    margin-top: 0 !important;
    .ycr{
      height: 36px;
    }
  }
</style>

父组件应用文件father.vue

代码如下:

<NTable
      :columns="columns"
      :data="tableList"
      :height="'650'"
      :pagination="pagination"
      rows-field="records"
      :table-type="'0'"
      :table-config="{ stripe: false }"
      :extend-search-fields="extendSearchFields"
      @on-change="changeHandle"
      @on-search="changeSearch"
      @on-reset="resetSearch"
    >
      <el-button v-hasPermi="['noumenon:link:add']" type="primary" @click="openTask">{{ title }}</el-button>
    </NTable>

表头参数culumns看这里:

举个栗子
//   表头
      columns: [
        {
          title: '序号',
          type: 'index',
          minWidth: 30,
          tooltip: true
        },
        {
          title: '目标类型',
          key: 'ontoClassify',
          minWidth: 60,
          tooltip: true,
          render: (h, params) => {
            if (params.row.ontoClassify === 0) {
              return <span>定制本体</span>
            } else if (params.row.ontoClassify === 1) {
              return <span>本体库</span>
            } else if (params.row.ontoClassify === 2) {
              return <span>项目库</span>
            }
          }
        },
        {
          title: '对应本体',
          key: 'ontoName',
          minWidth: 100,
          tooltip: true
        },
        {
          title: '任务名称',
          key: 'instanceName',
          minWidth: 100,
          tooltip: true
        },
        {
          title: '来源类型',
          key: 'instanceSource',
          minWidth: 70,
          tooltip: true,
          render: (h, params) => {
            return <span>{params.row.instanceSource === 1 ? '业务模型层' : '文件上传'}</span>
          }
        },
        {
          title: '源类型',
          key: 'originType',
          minWidth: 50,
          tooltip: true,
          render: (h, params) => {
            return <span>{params.row.instanceSource === 1 ? 'MySQL' : 'JSON'}</span>
          }
        },
        {
          title: '状态',
          key: 'instanceState',
          minWidth: 50,
          tooltip: true,
          render: (h, params) => {
            // instanceState=0失败 instanceState=1成功  instanceState=2执行中  instanceState=3暂停 instanceState=4停止 instanceState=5设置中
            if (params.row.instanceState === 1) {
              return (
                <span>
                  <i
                    class='dotClass'
                    style='background-color: springgreen;width:8px;  height:8px;  border-radius: 50%;  display: inline-block;  margin-right:3px'
                  ></i>
                  成功
                </span>
              )
            } else if (params.row.instanceState === 0) {
              return (
                <span>
                  <i
                    class='dotClass'
                    style='background-color: red;width:8px;  height:8px;  border-radius: 50%;  display: inline-block;  margin-right:3px'
                  ></i>
                  失败
                </span>
              )
            } else if (params.row.instanceState === 2) {
              return (
                <span>
                  <i
                    class='dotClass'
                    style='background-color: blue;width:8px;  height:8px;  border-radius: 50%;  display: inline-block;  margin-right:3px'
                  ></i>
                  执行中
                </span>
              )
            } else if (params.row.instanceState === 3) {
              return (
                <span>
                  <i
                    class='dotClass'
                    style='background-color: yellow;width:8px;  height:8px;  border-radius: 50%;  display: inline-block;  margin-right:3px'
                  ></i>
                  暂停
                </span>
              )
            } else if (params.row.instanceState === 4) {
              return (
                <span>
                  <i
                    class='dotClass'
                    style='background-color: red;width:8px;  height:8px;  border-radius: 50%;  display: inline-block;  margin-right:3px'
                  ></i>
                  停止
                </span>
              )
            } else if (params.row.instanceState === 5) {
              return (
                <span>
                  <i
                    class='dotClass'
                    style='background-color: #1C7FFD;width:8px;  height:8px;  border-radius: 50%;  display: inline-block;  margin-right:3px'
                  ></i>
                  设置中
                </span>
              )
            }
          }
        },
        {
          title: '创建时间',
          key: 'createdTime',
          minWidth: 120,
          tooltip: true,
          render: (h, params) => {
            // 日期格式化
            return <span>{dateFormat(params.row.createdTime)}</span>
          }
        },
        {
          title: '开始时间',
          key: 'startTime',
          minWidth: 120,
          tooltip: true,
          render: (h, params) => {
            // 日期格式化
            return (
              <span>
                {params.row.startTime === '' || params.row.startTime === null
                  ? '一 一'
                  : dateFormat(params.row.startTime)}
              </span>
            )
          }
        },
        {
          title: '结束时间',
          key: 'endTime',
          minWidth: 120,
          tooltip: true,
          render: (h, params) => {
            // 日期格式化
            return (
              <span>
                {params.row.endTime === '' || params.row.endTime === null ? '一 一' : dateFormat(params.row.endTime)}
              </span>
            )
          }
        },
        {
          title: '操作',
          key: 'action',
          width: 250,
          render: (h, params) => {
            const group = [
              <el-button
                type='text'
                size='small'
                onClick={() => {
                  this.showDetails = true
                  this.$nextTick(() => {
                    // this.$refs['instanceTaskDetails'].init(params.row.instanceSource)
                    this.$refs['instanceTaskDetails'].init(params)
                  })
                  // this.detail(params.row)
                }}
              >
                详情
              </el-button>,
              <el-button
                v-show={params.row.instanceState === 0}
                type='text'
                size='small'
                onClick={() => {
                  this.editModel(params.row, 'edit')
                }}
                v-hasPermi={['noumenon:link:edite']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                重新编辑
              </el-button>,
              <el-button
                v-show={params.row.instanceState === 5}
                type='text'
                size='small'
                onClick={() => {
                  this.editModel(params.row)
                }}
                v-hasPermi={['noumenon:link:edite']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                继续设置
              </el-button>,
              <el-button
                // 状态成功源类型是MySQL时显示数据更新按钮
                v-show={params.row.instanceState === 1 && params.row.instanceSource === 1}
                type='text'
                size='small'
                onClick={() => {
                  this.dataUpdate(params.row)
                }}
                v-hasPermi={['noumenon:link:update']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                数据更新
              </el-button>,
              <el-button
                v-show={params.row.instanceState === 0}
                type='text'
                size='small'
                onClick={() => {
                  this.showReason = true
                  this.$nextTick(() => {
                    this.$refs['ViewReason'].init(params.row.instanceId)
                  })
                }}
                v-hasPermi={['noumenon:link:findReason']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                查看原因
              </el-button>,
              <el-button
                v-show={params.row.instanceState === 2}
                type='text'
                size='small'
                onClick={() => {
                  this.suspend(params.row, 3)
                }}
                v-hasPermi={['noumenon:link:pause']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                暂停
              </el-button>,
              <el-button
                v-show={params.row.instanceState === 2}
                type='text'
                size='small'
                onClick={() => {
                  this.suspend(params.row, 4)
                }}
                v-hasPermi={['noumenon:link:end']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                终止
              </el-button>,
              <el-button
                v-show={params.row.instanceState === 3 || params.row.instanceState === 4}
                type='text'
                size='small'
                onClick={() => {
                  this.dataUpdate(params.row)
                }}
                v-hasPermi={['noumenon:link:start']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                启动
              </el-button>,
              <el-button
                v-show={params.row.instanceState !== 2}
                type='text'
                size='small'
                onClick={() => {
                  this.delList(params)
                }}
                v-hasPermi={['noumenon:link:delete']}
              >
                <span style='color:#eaeaea;margin-right:5px;height:10px;display:inline-block;line-height:10px'>|</span>
                删除
              </el-button>
            ]
            return <div class='iview-action'>{group}</div>
          }
        }
      ],

因为有render参数,所以组件需引入table.js,代码如下:

// table.js
export default {
  props: {
    render: {
      type: Function
    },
    param: {
      type: Object
    }
  },
  render(h) {
    return this.render(h, this.param)
  }
}

效果图看这里:

记得点赞

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue实现简易购物车案例

    Vue实现简易购物车案例

    这篇文章主要为大家详细介绍了Vue实现简易购物车案例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • Vue watch原理源码层深入讲解

    Vue watch原理源码层深入讲解

    watch 是由用户定义的数据监听,当监听的属性发生改变就会触发回调,这项配置在业务中是很常用。在面试时,也是必问知识点,一般会用作和 computed 进行比较。那么本文就来带大家从源码理解 watch 的工作流程,以及依赖收集和深度监听的实现
    2022-10-10
  • vue如何将字符串变为数组

    vue如何将字符串变为数组

    这篇文章主要介绍了vue如何将字符串变为数组问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • vue3中实现图片压缩的示例代码

    vue3中实现图片压缩的示例代码

    图片压缩是一种比较便捷的压缩方式,本文主要介绍了vue3中实现图片压缩的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02
  • VantUI封装自定义Tabbar路由跳转的实现

    VantUI封装自定义Tabbar路由跳转的实现

    本文主要介绍了VantUI封装自定义Tabbar路由跳转的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • vue使用swiper的时候第二轮事件不会触发问题

    vue使用swiper的时候第二轮事件不会触发问题

    这篇文章主要介绍了vue使用swiper的时候第二轮事件不会触发问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • vue实现书本翻页动画效果实例详解

    vue实现书本翻页动画效果实例详解

    这篇文章主要介绍了vue简单实现书本翻页效果,需要的朋友可以参考下
    2022-04-04
  • Vue 过渡实现轮播图效果

    Vue 过渡实现轮播图效果

    本篇文章主要介绍了Vue 过渡实现轮播图效果,Vue 的过渡系统是内置的,在元素从 DOM 中插入或移除时自动应用过渡效果。有需要的小伙伴可以参考下。
    2017-03-03
  • vue中如何创建多个ueditor实例教程

    vue中如何创建多个ueditor实例教程

    这篇文章主要给大家介绍了关于vue中如何创建多个ueditor的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-11-11
  • vue使用echarts如何实现双柱状图和双y轴的柱状图

    vue使用echarts如何实现双柱状图和双y轴的柱状图

    这篇文章主要介绍了vue使用echarts如何实现双柱状图和双y轴的柱状图问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10

最新评论