vue二次封装表格element-ui table

2 篇文章 1 订阅

vue基于element-ui table二次封装表格

封装的一些常用方法,如请求列表,render函数,复选框操作,合并行(合并列后续再添加),自适应高度;
列表请求支持两种方式:
1、子组件内请求(对于无需修改源数据的场景)
2、父组件请求,再把数据传到子组件(对于需要大量修改源数据的场景)

子组件MyTable/index.vue

<template>
  <div
    ref="tableBox"
    class="MyTable"
  >
    <!-- v-bind="$props": 可以将父组件的所有props下发给它的子组件,子组件需要在其props:{} 中定义要接受的props -->
    <!-- v-bind="$attrs": 将调用组件时的组件标签上绑定的非props的特性(class和style除外)向下传递。
  在子组件中应当添加inheritAttrs: false(避免父作用域的不被认作props的特性绑定应用在子组件的根元素上) -->
    <el-table
      ref="MyTable"
      v-loading="tableLoading"
      v-bind="$attrs"
      :data="dataSource"
      border
      fit
      highlight-current-row
      :height="relHeight"
      element-loading-text="数据加载中"
      element-loading-spinner="el-icon-loading"
      :row-class-name="tableRowClassName"
      :span-method="spanMethod"
      :row-key="getRowKey"
      @row-contextmenu="rowMenu"
      @selection-change="handleSelectionChange"
    >
      <!-- 复选框-->
      <el-table-column
        v-if="showSelection"
        type="selection"
        align="center"
        width="55"
        fixed
        :reserve-selection="!!reserveSelection"
      />
      <el-table-column
        v-if="showIndex"
        label="序号"
        type="index"
        width="55"
        min-width="50"
        max-width="60"
        align="center"
      />
      <template v-for="(col, key) in columns || []">
        <!-- 操作列/自定义列 -->
        <slot v-if="col.slot" :name="col.prop || col.slot" />
        <el-table-column
          v-else
          :key="key"
          :prop="col.prop"
          :label="col.label"
          :fixed="col.fixed"
          :width="col.width"
          :min-width="col.minWidth"
          :formatter="col.formatter"
          :align="col.align || 'left'"
        >
          <template slot-scope="scope">
            <!-- 正常渲染 -->
            <template v-if="!col.render">
              <template v-if="col.formatter">
                <span v-html="col.formatter(scope.row, col)" />
              </template>
              <template v-else>
                <span>{{ scope.row[col.prop] }}</span>
              </template>
            </template>
            <!-- render函数 -->
            <template v-else>
              {{ renderToHtml(col, scope.row) }}
              <slot :name="col.prop" />
            </template>
          </template>
        </el-table-column>
      </template>
      <!-- <template slot="empty">

      </template> -->
    </el-table>
    <!-- 是否调用分页 -->
    <el-pagination
      v-if="showPage"
      class="pagination-box"
      background
      :page-size="page.pageSize"
      :page-sizes="page.pageSizes"
      :current-page="page.current"
      layout="total,sizes, prev, pager, next,jumper"
      :total="page.total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import { equalsArr, unique, isObject } from '@/utils'
import request from '@/utils/request'

export default {
  name: 'MyTable',
  props: {
    // 是否显示分页
    showPage: {
      type: Boolean,
      default: () => { return false }
    },
    // 请求的url
    url: {
      type: String,
      default: () => { return '' }
    },
    // 请求参数
    params: {
      type: Object,
      default: () => { return {} }
    },
    // 是否需要复选框
    showSelection: {
      type: Boolean,
      default: () => { return false }
    },
    // 请求类型
    requestType: {
      type: String,
      default: () => { return 'get' }
    },
    // 表格数据,为兼容在父组件请求能使用子组件的页码,所以传进来的数据要求是一个对象
    tableData: {
      type: Object,
      default: () => { return { } }
    },
    // 表格列
    columns: {
      type: Array,
      default: () => { return [] }
    },
    // 表格高度
    height: {
      type: Number,
      default: () => { return null }
    },
    // 是否显示序号
    showIndex: {
      type: Boolean,
      default: () => { return true }
    },
    // 需要合并行的数组,传列的字段即可,如['name','title']
    spanProps: {
      type: Array,
      default: () => { return [] }
    },
    loading: {
      type: Boolean,
      default: () => { return false }
    },
    // 复选框选中的行
    selectRows: {
      type: Array,
      default: () => { return [] }
    },
    // 每行的唯一字段
    rowKey: {
      type: [Number, String],
      default: () => { return null }
    },
    // 数据更新之后保留之前选中的数据(需指定 row-key)
    reserveSelection: {
      type: Boolean,
      default: () => { return false }
    },
    // 数据结构支持传自定义的
    resConfig: {
      type: String,
      default: () => { return null }
    },
    // 数据结构字段支持传自定义的
    resName: {
      type: Object,
      default: () => {
        // return {
        //   data: 'data',
        //   total: 'total',
        //   pages: 'pages'
        // }
        return {}
      }
    }
  },
  data() {
    return {
      dataSource: this.tableData.data || [],
      tableLoading: this.loading,
      relHeight: this.height,
      multipleSelection: [],
      searchParams: {},
      resizeFn: null,
      page: {
        pageSize: 10,
        current: 1,
        pageSizes: [10, 20, 50, 100],
        total: 0
      }
    }
  },
  watch: {
    loading(val) {
      if (!this.url) {
        this.tableLoading = val
      }
    },
    tableData(val) {
      if (!this.url && isObject(val)) { // 父组件请求并且传过来的是一个对象
        this.dataSource = val.data
        if (val.total) this.$set(this.page, 'total', val.total) // 强制更新total
        this.setHeight()
      }
    },
    // 监听父组件传入的选中数据
    // 需要默认选中某些复选框时父组件传selectRows数组即可
    selectRows(val) {
      try {
        // 父组件选中的数组与子组件选中的数组比较,避免重复触发
        if (!equalsArr(val, this.multipleSelection)) {
          const oldSelectData = [...this.multipleSelection]
          this.$nextTick(async() => {
            await this.toggleSelection(val, oldSelectData)
          })
        }
      } catch (error) {
        console.log('🉐 ~ file: index.vue ~ line 177 ~ selectRows ~ error', error)
      }
    }
  },

  mounted() {
    this.resizeFn = this.resize()
    this.$nextTick(() => {
      if (!this.height) {
        // 监听窗口变化
        window.addEventListener('resize', this.resizeFn)
      }
    })
  },

  // 组件卸载
  destroyed() {
    // 移除窗口监听
    window.removeEventListener('resize', this.resizeFn)
    this.resizeFn = null
  },

  methods: {
    // 监听浏览器高度变化
    resize() {
      let timer = null
      return () => {
        if (timer) {
          window.clearTimeout(timer)
        }
        timer = window.setTimeout(() => {
          this.setHeight()
        }, 100)
      }
    },

    // 给表格行赋值唯一标识
    getRowKey(row) {
      return row[this.rowKey] || row.id || row.rowIndex || row.index
    },

    // 给数据增加index,为 Table 中的某一行添加 class
    tableRowClassName({ row, rowIndex }) {
      row.rowIndex = rowIndex
      if (row.rowClass) {
        return row.rowClass
      }
    },

    rowMenu(row, column, event) {
      this.$emit('handRowMenu', {
        row: row,
        column: column,
        event: event
      })
    },

    // 利用slot实现render函数jsx语法渲染
    renderToHtml(col, row) {
      if (typeof col.render === 'function') {
        this.$slots[col.prop] = [col.render(row)]
      }
    },

    // 复选框选择
    handleSelectionChange(val) {
      this.multipleSelection = val
      this.$emit('getSelectRows', val || [])
    },

    // 表格自适应高度
    setHeight() {
      this.relHeight = null
      this.$nextTick(() => {
        // this.relHeight = document.documentElement.clientHeight - 60 - 54;

        const MyTableRef = this.$refs.MyTable
        // 先清空上一次表格的高度再重新赋值,避免每次拿到的都是上一次设定的高度
        MyTableRef.$el.style.height = 'auto'
        if (this.height) {
          this.relHeight = this.height
        } else { // 父组件不传高度时表格高度自适应
          const tableBox = this.$refs.tableBox
          const alHeight = tableBox.clientHeight
          const tableBoxTop = tableBox.offsetTop
          const bodyHeight = document.body.clientHeight
          const tableBoxBottom = bodyHeight - tableBoxTop
          const isOverHeight = !!((alHeight || 0) - (tableBoxBottom || 0) > 0)

          if (isOverHeight) { // 表格高度是否超出浏览器高度
            this.relHeight = this.showPage ? tableBoxBottom - 42 - 120 : tableBoxBottom - 120
          } else {
            this.relHeight = this.showPage ? alHeight - 42 : alHeight
          }
        }
      })
    },

    // 如果是在父组件请求又需要分页,则在父组件调用这个方法
    setPage(params = {}) {
      if (!isObject(params)) return // 判断是否是对象
      const paramsNew = {
        ...this.searchParams,
        page: this.page.current,
        size: this.page.pageSize,
        ...params
      }
      this.searchParams = { ...paramsNew }
      return paramsNew
    },

    // 切换每页展示条数
    handleSizeChange(val) {
      this.$set(this.page, 'current', 1)
      this.$set(this.page, 'pageSize', val)
      if (!this.url) { // 如果是在父组件请求
        const params = {
          ...this.searchParams,
          page: this.page.current,
          size: this.page.pageSize
        }
        // 如果是在父组件请求,抛出这个切换方法给父组件
        this.$emit('handlePageChange', params)
      } else {
        this.getList()
      }
    },

    // 切换页码
    handleCurrentChange(val) {
      this.$set(this.page, 'current', val)
      if (!this.url) { // 如果是在父组件请求
        const params = {
          ...this.searchParams,
          page: this.page.current,
          size: this.page.pageSize
        }
        // 如果是在父组件请求,抛出这个切换方法给父组件
        this.$emit('handlePageChange', params)
      } else {
        this.getList().then(res => {
          this.setHeight()
        })
      }
    },

    // 搜索
    search(param = {}) {
      this.$set(this.page, 'current', 1)
      this.searchParams = { ...this.searchParams, ...param }
      this.getList(param)
    },

    // 重置
    handleReset() {
      return new Promise((resolve, reject) => {
        this.$set(this.page, 'current', 1)
        this.$set(this.page, 'pageSize', 10)
        this.searchParams = {}
        this.getList().then(res => {
          resolve(res)
        })
      })
    },

    // 请求列表
    getList(param = {}) {
      return new Promise((resolve, reject) => {
        // 父组件可以传params,如果不传,可在调用getList方法时以参数形式传
        // param调用方法时传的参数
        // this.params通过调用组件传的参数
        // this.searchParams子组件用来缓存所有传进来的参数,方便切换页码时用到
        this.tableLoading = true
        this.dataSource = []
        this.searchParams = { ...this.searchParams, ...param }
        let paramsNew = Object.assign({}, this.params)
        paramsNew = { ...paramsNew, ...this.searchParams }

        // 是否需要分页
        if (this.showPage) {
          paramsNew.page = this.page.current
          paramsNew.size = this.page.pageSize
        }
        const paramsKey = { params: paramsNew }

        if (!['get', 'GET'].includes(this.requestType)) {
          // 非get请求时的处理
          paramsKey.data = paramsNew
          delete paramsKey.params
        }
        request({
          url: this.url,
          method: this.requestType || 'GET',
          ...paramsKey
        })
          .then((res) => {
            this.tableLoading = false
            // 数据结构及字段支持传自定义的
            // :resConfig="res.data.data"  数据结构
            // :resName="{data:'data',total:'total',pages:'pages'}"  字段名称
            const option = this.resConfig && typeof this.resConfig === 'string'
            let newRes = res
            if (option) {
              const level = this.resConfig.split('.')
              if (level.length > 1) {
                level.map((item, index) => {
                  if (item !== 'res') {
                    newRes = newRes [item]
                  }
                })
              }
            }

            // ?.是可选链符的写法,其实props已经定义了this.resName的默认值为{},可以不用可选链符判断,直接写成this.resName.data也可
            const records = res[this?.resName?.data] || res.records || []
            const total = res[this?.resName?.total] || res.total || 0
            const pages = res[this?.resName?.pages] || res.pages || 0

            if (pages) {
              this.$set(this.page, 'total', total) // 强制更新界面
              this.dataSource = option ? newRes || [] : records
              // this.setHeight()
              resolve(records)
            }
          })
          .catch((err) => {
            this.tableLoading = false
            reject()
          })
      })
    },

    // 复选框默认选中处理
    async toggleSelection(val, oldSelectData) {
      // 提取rowKey数组
      const selectKeys = (val || []).map(item => (item[this.rowKey] || item.id))
      // 解决操作删除标签时,上一页的数据无法被删除问题
      const deleteData = (oldSelectData || []).filter(item => !selectKeys.includes(item[this.rowKey]));
      (deleteData || []).map((item) => {
        this.$refs.MyTable.toggleRowSelection(item, false)
      })
      // 调用toggleRowSelection方法会触发复选框change事件,选中的值会被改变,所以要合并数组
      let newDataSource = [...this.dataSource, ...val]
      newDataSource = unique(newDataSource, this.rowKey); // 去重

      (newDataSource || []).map(item => {
        const rowKey = item[this.rowKey] || item.id
        if (selectKeys.includes(rowKey)) {
          // 设置选中
          this.$refs.MyTable.toggleRowSelection(item, true)
        } else {
          // 取消选中
          this.$refs.MyTable.toggleRowSelection(item, false)
        }
      })
      return Promise.resolve()
    },

    // 合并行
    // 参数:dataSource-表格数据,spanProps-需要进行合并计算的字段列表,rowIndex-当前行数,columnIndex-当前列数,column-当前列
    spanMethodFunc(dataSource = [], spanProps = [], rowIndex, columnIndex, column) {
      // if (columnIndex >= spanProps.length || !spanProps[columnIndex]) {
      if (!spanProps.includes(column.property)) {
        // 根据传入的字段列表,判断不需要合并的列
        return [1, 1]
      } else {
        // 使用try-catch,如果方法错误返回错误信息
        try {
          // let _spanProps = spanProps.slice(columnIndex, columnIndex + 1); //截取需要用到判断的字段名
          // 过滤出需要合并的当前列字段
          const _spanProps = spanProps.filter(item => item == column.property)
          // 判断是否从本行开始合并
          const merge = _spanProps.some((item) => {
            // 如果当前行所需要判断合并的字段中有一个跟前一条数据不一样,本条数据即为合并的起点,第一条数据直接为合并起点
            return rowIndex == 0 || (item && dataSource[rowIndex][item] != dataSource[rowIndex - 1][item])
          })
          // 如果本条数据是合并起点,获取需要合并的数据条数
          if (merge) {
            const _list = dataSource.slice(rowIndex) // 截取从本条数据开始的列表
            // 获取合并行数
            const _lineNum = _list.findIndex((item, index) => {
              // 同merge判断,找到合并的终点
              return (
                index &&
                _spanProps.some((item1) => {
                  return item1 && item[item1] != _list[0][item1]
                })
              )
            })
            // 合并行数为-1时,输出_list的长度,否则输出_lineNum
            return [_lineNum === -1 ? _list.length : _lineNum, 1]
          } else {
            // 否则,返回[0,0],即本条数据被合并
            return [0, 0]
          }
        } catch (err) {
          console.error('spanMethodFunc error:', err)
        }
      }
    },

    // 合并行
    spanMethod({ row, column, rowIndex, columnIndex }) {
      return !this.spanProps || this.spanProps.length === 0 ? false : this.spanMethodFunc(this.dataSource, this.spanProps, rowIndex, columnIndex, column)
    }

  }
}

</script>

<style scoped lang="scss">
  .pagination-box {
    margin-top: 10px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    text-align: right;
  }
</style>


以上就是封装的组件了,下面开始使用

父组件调用(方式一:直接调用子组件内的请求方法,一定要传url)

<template>
  <div>
      <standar-table
        ref="elTableList" 
        :url="url.getWKEventListlUrl" 
        :isShowPage="true"
        :showSelection="true"
        :columns="columns"
        @getSelectRows="getSelectRows"
      >
      <el-table-column
        slot="oprate"
        :key="oprate"
        label="是否启用"
        align="center"
      >
        <template slot-scope="scope">
          <el-switch
            class="mySwitch"
            v-model="scope.row.status"
            active-text="启用"
            inactive-text="禁用"
            :active-value="1"
            :inactive-value="0"
            @change="handleStatusChange($event,scope.row)"
          >
          </el-switch>
        </template>
      </el-table-column>
      </standar-table>
  </div>
</template>

// 存放接口文件:point.js
// export const getWKEventListlUrl = '/api/aaaaa/bbbbb';

<script>
	import standarTable from '@/components/MyTable/index'
	import {getWKEventListlUrl,eventExport} from "@/api/point";
	
	export default {
		components:{standarTable},
		data() {
	      return {
	        searchform: {},
	        url:{getWKEventListlUrl},
	        columns: [
	          {
	            label: "埋点事件",
	            prop: "eventName",
	            align:'center',
	            // render:(row) => {
	            //	 retrun row.eventName
	            // }
	          },
	          {
	            label: "类型",
	            prop: "typeName",
	            align:'center',
	          },
	          {
	            label: "是否启用",
	            slot: "oprate",
	            prop: "oprate",
	            align:'center',
	          },
	        ],
	        selectRows:[],
	        selectRowsData:[],
	      };
	    },
	    methods: {
	      // 公共参数
	      getParams(){
	        const params = {
	          ...this.searchform,
	          type:this.searchform.type.join(',')
	        };
	        return params;
	      },
	      // 请求列表
	      getListData() {
	        this.$refs.elTableList.search(this.getParams())
	      },
	      // 表格复选框选中
	      getSelectRows(data){
	        this.selectRows = data || [];
	      },
	      // 状态change
	      handleStatusChange(v,{eventCode = '',status = 0}){
	        const messageText = {
	          0:'禁用成功',
	          1:'启用成功'
	        }
	        const params = {eventCode,status};
	        setEventStatus(params).then(res => {
	          if(res.data.code === 200){
	            this.$message.success(messageText[v]);
	            this.getListData();
	          }
	        }).catch(err => {
	          console.log('🉐 ~ file: wkEvent.vue ~ line 154 ~ setEventStatus ~ err', err);
	        })
	      },
	      // 清空选中的数据
	      clearData(){
	        this.selectRowsData = [];
	      }
	    },
	    mounted() {
			// 通过ref调用子组件里面的列表请求方法
	      this.$refs.elTableList.getList(this.getParams());
	    }
	}
</script>	

效果图:
在这里插入图片描述
父组件调用(方式二:在父组件请求,不需要页码,需要合并行,传数据到子组件,不必传url了,tableData必须是一个对象)

<template>
  <div>
      <standar-table
        ref="elTableList" 
        :columns="columns"
        :showIndex="false"
        :tableData="tableData"
        :loading="tableLoading"
        :spanProps="spanProps"
        :height="'90vh'"
      >
        <el-table-column
          slot="oprate"
          key="oprate"
          label="门槛条件"
          align="center"
        >
          <template slot-scope="scope">
            <span class="mgr10">经验值达到</span>
            <inputNumber 
              :value="scope.row.experienctThreshole" 
              v-model="scope.row.experienctThreshole" 
              :controls="false"
              :min="0" 
              @change="inputNumberChange($event,scope.row,'experienctThreshole')"
            />
          </template>
        </el-table-column>
        <el-table-column
          slot="rankStartThreshole"
          key="rankStartThreshole"
          label="排名要求"
          align="center"
        >
          <template slot-scope="scope">
            <div v-if="sameType1.includes(scope.row.titleName)">--</div>
            <div v-else>
              <span class="mgr10">排名</span>
              <inputNumber 
                :value="scope.row.rankStartThreshole" 
                v-model="scope.row.rankStartThreshole" 
                :controls="false"
                :min="0" 
                style="width:30%"
                @change="inputNumberChange($event,scope.row,'rankStartThreshole')"
              /> - 
              <inputNumber 
                :value="scope.row.rankEndThreshole" 
                v-model="scope.row.rankEndThreshole" 
                :controls="false"
                :min="0" 
                style="width:30%"
                @change="inputNumberChange($event,scope.row,'rankEndThreshole')"
              />
              <span class="mgl10">以内</span>
            </div>
          </template>
        </el-table-column>
      </standar-table>
  </div>
</template>

// 存放接口文件:point.js
// export const getStatusLevelList= '/api/aaaaa/bbbbb';

<script>
	import standarTable from '@/components/MyTable/index'
	import {getStatusLevelList} from "@/api/point";
	
	export default {
		components:{standarTable},
		data() {
	      return {
	        columns: [
	          {
	            label: "学籍",
	            prop: "titleName",
	            align:'center',
	          },
	          {
	            label: "段位分类",
	            prop: "topRank",
	            align:'center',
	            render:(row) => {
	              const sameType1 = ['童生','秀才'];
		          const sameType2 = ['举人','进士'];
		          const sameType3 = ['探花','榜眼','状元'];
	              let topText = '低级';
	              let bottomText = `比例后60%(${row.lowRank}为预设总数)`;
	              const type2 = sameType2.includes(row.titleName);
	              const type3 = sameType3.includes(row.titleName);
	              if(type2) topText = '中级';
	              if(type3) topText = '高级';
	              return <div class="textLeft">{`${topText}段位排名 ${row.topRank} - ${row.lowRank + bottomText}`}</div>
	            }
	          },
	          {
	            label: "等级分类",
	            prop: "titleCount",
	            align:'center',
	          },
	          {
	            label: "门槛条件",
	            slot: "oprate",
	            prop: "oprate",
	            align:'center',
	          },
	          {
	            label: "排名要求",
	            prop: "rankStartThreshole",
	            slot: "rankStartThreshole",
	            align:'center',
	          },
	          {
	            label: "排名称号",
	            prop: "experienceRank",
	            align:'center',
	          },
	        ],
	        tableData:{},
	        tableLoading:false,
	        spanProps:['titleName','topRank','titleCount'],  // 需要合并行的字段  
	      };
	    },
	    methods: {
	      // 公共参数
	      getParams(){
	        const params = {
	          ...this.searchform,
	        };
	        return params;
	      },
	      // 请求列表
	      getListData() {
	        this.tableLoading = true;
	        try {
	          getStatusLevelList(this.getParams()).then(res => {
	            if(res.data.code === 200){
	              this.tableLoading = false;
	              const data = res.data.data || [];
	              const newData = this.filterData(data);
	              this.tableData = {data:newData};
	            }
	          }).catch(err => {
	            this.tableLoading = false;
	          })
	        } catch (error) {
	          this.tableLoading = false;
	        }
	      },
	      // 列表数据处理
	      filterData(data = []){
	        let tableData = [];
	        (data || []).map(item => {
	          const pItem = Object.assign({},item);
	          const detailListNew = (item.detailList || []).map(cItem => {
	            return {
	              ...pItem,
	              ...cItem,
	            }
	          });
	          tableData = [...tableData,...detailListNew]
	        });
	        return tableData;
	      },
	      // inputNumber change
	      inputNumberChange(v,row,type){
	
	      },
	    },
	    mounted() {
	      this.getListData();
		}
</script>

效果图:
在这里插入图片描述
父组件调用(方式三:在父组件请求,并且需要页码,不传url,tableData必须是一个对象)

<template>
  <div class="containerMargin">
 	<el-form
      ref="searchForm"
      :model="searchForm"
      label-position="right"
    >
      <el-row :gutter="20">
        <el-col :span="6">
          <el-form-item>
            <el-input
              v-model="searchForm.tagName"
              placeholder="客户标签"
              clearable
            />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <standarTable
      ref="myTable"
      :columns="columns"
      :show-page="true"
      :show-index="false"
      request-type="post"
      :table-data="tableData"
      @handlePageChange="handlePageChange"
    />
  </div>
</template>

<script>
// 存放接口文件:point.js
import {page} from "@/api/point";
import standarTable from '@/components/MyTable/index'

export default {
  name: 'MassMediaDeliveryManagement',
  components: { standarTable },
  data() {
    return {
      searchForm: {}, // 分页参数
      tableData: {},
      columns: [
        {
          label: 'ID',
          prop: 'id',
          align: 'center',
          width: 200
        },
        {
          label: '标签类型',
          prop: 'deleteTag',
          align: 'center'
        },
        {
          label: '客户标签',
          prop: 'tagName',
          align: 'center'
        },
        {
          label: '创建人',
          prop: 'createUser',
          align: 'center'
        },
        {
          label: '创建时间',
          prop: 'createTime',
          align: 'center',
          render: (row) => {
            // return formatDate(row.createTime, true)
          }
        }
      ]
    }
  },
  mounted() {
    this.getListData()
  },

  methods: {
    // 公共参数
    getParams() {
      const params = {
        ...this.searchForm
      }
      return params
    },
    // 请求列表
    getListData() {
      this.$nextTick(() => {
        const params = this.$refs.myTable.setPage(this.getParams())
        page(params).then(res => {
          this.tableData = { data: res.records || [], total: res.total }
        })
      })
    },
    // 切换页码
    handlePageChange(params) {
      this.getListData()
    }
  }
}
</script>

效果图:在这里插入图片描述

公共方法: utils/index.js

/** 判断是否是数组
 * @param {Object} value
 * 返回true或false
 */
export function isArrayFn(value) {
  if (typeof Array.isArray === 'function') {
    return Array.isArray(value)
  }
  return Object.prototype.toString.call(value) === '[object Array]'
}

/**
 * 比较两个数组是否相等
 *@param{Arry}arr1 需要比较的数组1
*@param{Arry}arr2 需要比较的数组2
*/
export function equalsArr(arr1 = [], arr2 = []) {
  if (!isArrayFn(arr1) || !isArrayFn(arr2)) return
  if (JSON.stringify(arr1) == JSON.stringify(arr2)) return true
  return false
}

// 数组去重
export function unique(data = [], key) {
  if (!data) return
  const res = new Map()
  return data.filter(a => !res.has(a[key]) && res.set(a[key], 1))
}

/** 判断是否是对象
 * @param {Object} value
 * 返回true或false
 */
export function isObject(value) {
  if (Object.prototype.toString.call(value) === '[object Object]') {
    return true
  }
  return false
}
  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值