115.《table组件的二次封装》

1.组件封装

<template>
  <div>
    <el-table
      ref="multipleTable"
      v-loading="loading"
      :data="tableData"
      border
      fit
      :row-key="getRowkeys"
      @row-click="handleRowClick"
      @sort-change="handleSort"
      @filter-change="filterHandler"
      @selection-change="handleSelectionChange"
    >
      <!-- 多选框 -->
      <el-table-column v-if="selectionShow" :selectable="checkSelectable" type="selection" width="50" align="center" :reserve-selection="true" />
      <el-table-column v-if="indexShow" type="index" :index="typeIndex" label="序号" width="50" align="center" />
      <el-table-column
        v-for="(th, key) in tableHeader"
        :key="key"
        :prop="th.prop"
        :label="th.label"
        :fixed="th.fixed"
        :sortable="th.custom?'custom':false"
        :filters="th.filters"
        :column-key="th.columnKey"
        :filtered-value="th.filteredValue"
        :filter-multiple="th.filterMultiple"
        :min-width="th.minWidth || 120"
        :width="th.width"
        :show-overflow-tooltip="!th.noTooltip"
        :class-name="th.className"
        :align="th.align || 'center'"
      >
        <template slot-scope="scope">
          <!-- 自定义插槽 -->
          <slot v-if="th.type == 'slot'" :name="th.prop" :row="scope.row" />
          <!-- 操作按钮 -->
          <template v-else-if="th.type == 'button'">
            <template v-for="(o, i) in th.operation">
              <el-button
                v-if="o.isHide ? o.isHide(scope.row) : true"
                :key="i"
                :type="o.type || 'text'"
                @click="o.clickFun(scope.row)"
                @mousedown="o.mousedown(scope.row, $event)"
              >
                {{ o.name }}
              </el-button>
            </template>
          </template>
          <!-- 点击跳转页面 -->
          <router-link v-else-if="th.type == 'router'" :to="{path: th.path, query: th.query(scope.row)}">
            <span
              :class="typeof th.itemClassName == 'function'
                ? th.itemClassName(scope.row) : th.itemClassName"
              v-html="handleFilter(th, scope.row, th.prop)"
            />
          </router-link>
          <!-- 输入框 -->
          <el-input
            v-else-if="typeof th.type == 'function' ? th.type(scope.row) == 'input': th.type == 'input'"
            v-model="scope.row[th.prop]"
            @keyup.enter.native="th.change && th.change(scope.row)"
          />
          <el-switch
            v-else-if="th.type == 'switch'"
            v-model="scope.row[th.prop]"
            active-color="#13ce66"
            inactive-color="#ff4949"
            :active-value="1"
            :inactive-value="0"
            @change="th.handelChange(scope.row, $event)"
          />
          <span
            v-else
            :class="typeof th.itemClassName == 'function' ? th.itemClassName(scope.row) : th.itemClassName"
            v-html="handleFilter(th, scope.row, th.prop)"
          />
        </template>
      </el-table-column>
    </el-table>
    <div class="pagination" :style="{textAlign:`${pagination_loaction}`}">
      <el-pagination
      v-if="total > 0"
      background
      layout="total, prev, pager, next"
      class="text-center mt_20"
      :current-page="page"
      :page-size="limit"
      :total="total"
      @current-change="handleCurrentChange"
    />
    </div>

  </div>
</template>

<script>
export default {
  name: 'CompTable',
  filters: {
    formatters (val, format) {
      if (typeof (format) === 'function') {
        return format(val)
      } else return val
    }
  },
  props: {
    showRowKey: {
      type: Boolean,
      default: false
    },
    tableData: {
      type: Array,
      default: function () {
        return []
      }
    },
    tableHeader: {
      type: Array,
      default: function () {
        return []
      }
    },
    multipleSelection: {
      type: Array,
      default: function () {
        return []
      }
    },
    loading: {
      type: Boolean,
      default: false
    },
    selectionShow: {
      type: Boolean,
      default: false
    },
    indexShow: {
      type: Boolean,
      default: false
    },
    page: {
      type: Number,
      default: 1
    },
    limit: {
      type: Number,
      default: 10
    },
    total: {
      type: Number,
      default: 0
    },
    pagination_loaction: {
      type: String,
      default: 'right'
    }
  },
  methods: {
    // 处理表格序号
    typeIndex (index) {
      const vm = this // 处理分页数据的 index
      return (vm.page - 1) * vm.limit + index + 1
    },
    // 数据处理
    handleFilter (item, val, prop) {
      let value = val[prop]
      if (item.templet) value = item.templet(val)
      return item.filter ? this.$options.filters[item.filter](val[prop]) : value
    },
    handleSelectionChange (val) {
      this.$emit('multiple-Selection', val)
    },
    handleSort (sort) {
      this.$emit('sort-events', sort)
    },
    filterHandler (filters) {
      this.$emit('filter-events', filters)
    },
    // 当前页改变触发
    handleCurrentChange (val) {
      this.$emit('current-events', val)
    },
    handleRowClick (row, column) {
      this.$emit('handle-row-click', row, column)
    },
    checkSelectable (row) {
      let isshow = false
      if (row.status === 1) {
        isshow = false
      } else {
        isshow = true
      }
      return isshow

      // return !row.status || row.status === 1
    },
    getRowkeys (row) {
      if (this.showRowKey) {
        return row.bill_data_id
      }
    },
    // 清空
    clearSelection () {
      this.$refs.multipleTable.clearSelection()
    }
  }
}
</script>

<style>
body .el-table th.gutter {
  display: table-cell!important;
}
body .pagination {
  margin-top: 10px;
}
</style>

2.全局注册

import compTable from '@/components/compTable'
Vue.use(compTable)

3.全局使用

import compTable from '@/components/compTable'
Vue.use(compTable)

4.页面使用

<template>
  <div class="wrap">
      <el-card class="card-box">
        <!--
          1.formData:
            说明: form 表单绑定的值
            类型:Object
            案例:
            formData: {
               name: 1,
            }
          2.formArr
            说明: 文本框的 label
            类型:Array
            案例:
            formArr: [{
                type: 'select',
                label: '筛选类型',
                prop: 'type',
                placeholder: '全部',
                optionLabelName: 'label',
                optionValueName: 'type',
                closeClearable: true
              }]
          3.btnArr
            说明: 按钮
            类型:Array
            案例:
            btnArr: [
              { label: '查询', type: 'primary', handle: () => this.handleSearch() }
            ]
          4.inline
           说明: 是否是行内表单
           类型:Boolean
           案例,
           :inline='true'
         5.formWidth
           说明:整个表单的宽度
           类型:String
           案例,
           :formWidth='formWidth', data 中定义 formWidth:200
        6.
      -->
        <fr-form
         ref="formData"
         form-name="formData"
        :form-data="formData"
        :form-arr="formArr"
        :labelWidth="labelWidth"
        :btn-arr="btnArr"
        :inline='false'
        :rules="formRules"
        :formWidth='formWidth'
        />
      </el-card>
  </div>
</template>

<script>
export default {
  data () {
    return {
      formWidth: '200',
      labelWidth: '100px',
      size: 'medium',
      formData: {
        select: '',
        input: '',
        textarea: '',
        number: '',
        tel: '',
        password: '',
        radio: 0,
        radioButton: 0,
        checkbox: ['北京'],
        cascader: '',
        date: '',
        switch: '',
        // img: '',
        tinymce: ''
      },
      btnArr: [
        { label: '确认', type: 'primary', handle: () => this.handleSearch('formData') },
        { label: '重置', type: 'success', handle: () => this.handleReset('formData') },
        { label: '刷新', type: 'plain', handle: () => this.handleFresh() }
      ],
      formArr: [
        {
          type: 'divider',
          title: '标题栏'
        },
        { type: 'select',
          label: 'select',
          prop: 'select',
          placeholder: '全部',
          optionLabelName: 'label',
          optionValueName: 'value',
          closeClearable: true,
          disabled: () => this.disabled(),
          change: () => this.selectChange(),
          visibleChange: () => this.visibleChange(),
          options: () => this.initSelectValue()
        },
        { type: 'input',
          label: 'input',
          childWidth: '220px',
          prop: 'input',
          placeholder: '请输入',
          handle: () => this.backEnter(),
          closeClearable: true
        },
        {
          type: 'textarea',
          label: 'textarea',
          prop: 'textarea',
          childWidth: '420px',
          placeholder: '请输入',
          optionLabelName: 'label',
          maxlength: '10',
          closeClearable: true
        },
        {
          type: 'number',
          label: 'number',
          prop: 'number',
          placeholder: '请输入',
          childWidth: '420px'
        },
        {
          type: 'tel',
          label: 'tel',
          prop: 'tel',
          placeholder: '请输入',
          maxlength: 11,
          change: () => this.telChange(),
          childWidth: '420px'
        },
        {
          type: 'password',
          label: 'password',
          prop: 'password',
          placeholder: '请输入',
          maxlength: 11,
          childWidth: '420px'
        },
        {
          type: 'radio',
          label: 'radio',
          prop: 'radio',
          radios: [
            {
              label: '北京',
              value: 0
            },
            {
              label: '上海',
              value: 1
            },
            {
              label: '广州',
              value: 2
            },
            {
              label: '深证',
              value: 3
            }
          ],
          change: (e) => this.radioChange(e)
        },
        {
          type: 'radioButton',
          label: 'radioButton',
          prop: 'radioButton',
          radios: [
            {
              label: '北京',
              value: 0
            },
            {
              label: '上海',
              value: 1
            },
            {
              label: '广州',
              value: 2
            },
            {
              label: '深证',
              value: 3
            }
          ],
          change: (e) => this.radioButtonChange(e)
        },
        {
          type: 'checkbox',
          label: 'checkbox',
          prop: 'checkbox',
          childWidth: '420px',
          change: (e) => this.CheckButtonChange(e),
          checkboxs: this.checkBoxList()
        },
        {
          type: 'cascader',
          prop: 'cascader',
          label: 'Cascader',
          placeholder: '请选择',
          childWidth: '300px',
          options: () => this.CascaderOptions(),
          change: () => this.cascaderChange()
        },
        {
          type: 'date',
          prop: 'date',
          label: 'date',
          placeholder: '请选择',
          childWidth: '300px'
        },
        {
          type: 'switch',
          prop: 'switch',
          label: 'switch',
          placeholder: '请选择'
        },
        {
          type: 'tinymce',
          label: 'tinymce',
          prop: 'tinymce',
          childWidth: '300px'
        }
      // {
      //   type: 'img',
      //   prop: 'img',
      //   limit: 1,
      //   label: 'img',
      //   remark: '',
      //   placeholder: '请选择'
      // }
      ],
      formRules: {
        select: [ { required: true, message: '请选择', trigger: 'change' } ],
        input: [ { required: true, message: '请输入', trigger: 'change' } ],
        textarea: [ { required: true, message: '请输入', trigger: 'change' } ],
        number: [ { required: true, message: '请输入', trigger: 'change' } ],
        tel: [ { required: true, message: '请输入', trigger: 'change' } ],
        password: [ { required: true, message: '请输入', trigger: 'change' } ],
        radio: [ { required: true, message: '请选择', trigger: 'change' } ],
        radioButton: [ { required: true, message: '请选择', trigger: 'change' } ],
        checkbox: [ { required: true, message: '请选择', trigger: 'change' } ],
        cascader: [ { required: true, message: '请选择', trigger: 'change' } ],
        date: [ { required: true, message: '请选择', trigger: 'change' } ],
        tinymce: [ { required: true, message: '请输入', trigger: 'change' } ],
        img: [ { required: true, message: '请选择', trigger: 'change' } ]
      },
      checkBox: [{
        label: '北京',
        value: 0
      },
      {
        label: '上海',
        value: 1
      }]
    }
  },
  methods: {
    // 查询
    async handleSearch (formData) {
      if (await this.$refs.formData.validate(formData)) {
        console.log('表单数据', this.formData)
        this.$success('验证通过过')
      } else {
        this.$error('验证失败')
      }
    },
    // 下拉框数据
    initSelectValue () {
      return [
        { label: '订阅号', value: 'subscribe' },
        { label: '服务号', value: 'server' }
      ]
    },
    // 下拉框出现/隐藏时触发,出现则为 true,隐藏则为 false
    visibleChange () {
      this.$success('下拉框触发')
    },
    // 下拉框 发生改变
    selectChange () {
      this.$success('下拉框改变触发')
    },
    // tel 发生改变
    telChange () {
      this.$success('手机狂变动输入')
    },
    // 单选
    radioChange (e) {
      console.log('单选按钮', e)
      this.$success('单选按钮')
    },
    // 单选按钮
    radioButtonChange (e) {
      console.log('radioButtonChange', e)
    },
    // 复选框数据
    checkBoxList () {
      return [{
        label: '北京',
        value: 0
      },
      {
        label: '上海',
        value: 1
      }]
    },
    // 复选框的值改变
    CheckButtonChange (e) {
      console.log('复选框的值改变', e)
    },
    // 级联数据
    CascaderOptions () {
      return [
        {
          value: 'zhinan',
          label: '指南',
          children: [{
            value: 'shejiyuanze',
            label: '设计原则',
            children: [{
              value: 'yizhi',
              label: '一致'
            }, {
              value: 'fankui',
              label: '反馈'
            }, {
              value: 'xiaolv',
              label: '效率'
            }, {
              value: 'kekong',
              label: '可控'
            }]
          }, {
            value: 'daohang',
            label: '导航',
            children: [{
              value: 'cexiangdaohang',
              label: '侧向导航'
            }, {
              value: 'dingbudaohang',
              label: '顶部导航'
            }]
          }]
        }
      ]
    },
    // 级联选择器z
    cascaderChange (e) {
      console.log('级联选择器--cascaderChange', e)
    },
    // 刷新
    handleFresh () {
      this.$success('刷新')
      /* 强制刷新
         this.$router.go(0)
      */
    },
    // 重置
    handleReset (formName) {
      this.$refs[formName].resetForm()
      this.$success('重置')
    },
    // 是否重置
    disabled () {
      return false
    },
    // 输入框回车键
    backEnter () {
      this.$success('你点击了 Enter 键')
    }
  }
}
</script>

<style scoped lang="less">
.wrap{
  height: 200px;
}

</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值