使用element-ui怎么封裝一個Table模板組件-創(chuàng)新互聯(lián)

今天就跟大家聊聊有關(guān)使用element-ui怎么封裝一個Table模板組件,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

專業(yè)領(lǐng)域包括網(wǎng)站制作、做網(wǎng)站、購物商城網(wǎng)站建設(shè)、微信營銷、系統(tǒng)平臺開發(fā), 與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開發(fā)公司不同,創(chuàng)新互聯(lián)的整合解決方案結(jié)合了幫做網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營銷的理念,并將策略和執(zhí)行緊密結(jié)合,為客戶提供全網(wǎng)互聯(lián)網(wǎng)整合方案。

大家在做后臺管理系統(tǒng)的時候,寫的最多的可能就是表格頁面了,一般分三部分:搜索功能區(qū)、表格內(nèi)容區(qū)和分頁器區(qū)。一般這些功能都是使用第三方組件庫實(shí)現(xiàn),比如說element-ui,或者vuetify。這兩個組件庫都各有各的優(yōu)點(diǎn),但就table組件來說,我還是比較喜歡vuetify的實(shí)現(xiàn),不用手寫一個個column,只要傳入headers的配置數(shù)組就行,甚至分頁器都內(nèi)置在了table組件里,用起來十分方便。有興趣可以看看:vuetify data table。

使用element-ui怎么封裝一個Table模板組件

上面是一個經(jīng)典的用element-ui開發(fā)的table頁面,而且實(shí)際工作中如果每個table頁面都寫一遍,重復(fù)代碼太多了,所以不妨寫一個table模板組件,減少重復(fù)代碼。我的思路是這樣的:

搜索功能區(qū):

提供searchBar插槽,可以自定義搜索輸入框,搜索、重置按鈕必有,新增按鈕通過props控制顯隱。這里對應(yīng)的代碼如下:

genSearchBar() {
  if (this.noSearchBar || !this.$scopedSlots.searchBar) return '';
  return (
    <el-form class="seatch-form" inline={true} label-width="100">
      {this.$scopedSlots.searchBar()}
      <el-button
        class="filter-item"
        icon="el-icon-search"
        type="primary"
        onClick={this.handleSearchBtnClick}
      >
        查詢
      </el-button>
      <el-button
        class="filter-item"
        icon="el-icon-refresh"
        onClick={this.handleResetBtnClick}
      >
        重置
      </el-button>
      <el-button
        class="filter-item"
        icon="el-icon-plus"
        type="primary"
        v-show={this.showAddBtn}
        onClick={this.handleAddBtnClick}
      >
        新增
      </el-button>
    </el-form>
  );
}

表格內(nèi)容區(qū):

通過傳入headers自動生成columns,參數(shù)如下:

{
  label: '性別',
  prop: 'sex',
  width: '180',
  filter: 'sexFilter'
}

可對應(yīng)如下代碼:

<el-table-column
         prop="sex"
         label="性別"
         width="180">
  <template slot-scope="scope">{{scope.row.sex | sexFilter}}</template>
</el-table-column>

注意,只支持全局filter。

如果你想自定義column,也提供tableColumn插槽,支持自定義column,可以如下配置:

{
  prop: 'action'
}
<el-table-column
         prop="action"
         label="操作"
         width="180">
  <template slot-scope="scope">
    <el-button>編輯</el-button>
    <el-button>刪除</el-button>
  </template>
</el-table-column>

這樣,就會按傳入的prop匹配對應(yīng)的column,十分方便。

實(shí)現(xiàn)代碼如下:

genTableSlot(h) {
  let customeColumns = this.$scopedSlots.tableColumn
    ? this.$scopedSlots.tableColumn()
    : [];
  return this.headers.map((item) => {
    // 根據(jù)item.prop判斷是否使用傳入的插槽內(nèi)容
    let foundItem = customeColumns.find(
      (ele) =>
        ele.componentOptions &&
        ele.componentOptions.propsData.prop === item.prop
    );
    return foundItem
      ? foundItem
      : h('el-table-column', {
         props: {
           ...item,
         },
         scopedSlots: {
           default: (props) => {
             // 根據(jù)傳入的全局filter處理column數(shù)據(jù)
             let filter = this.$options.filters[
               item.filter
             ];
             let itemValue = props.row[item.prop];
             return h(
               'span',
               filter ? filter(itemValue) : itemValue
             );
           },
         },
       });
  });
}
genTable(h) {
  return h(
    'el-table',
    {
      ref: 'tableRef',
      props: {
        ...this.$attrs,
        data: this.data,
      },
      on: {
        'selection-change': (val) => {
          this.$emit('selection-change', val);
        },
      },
    },
    [...this.genTableSlot(h)]
  );
}

分頁器區(qū):

如無特殊需求,分頁器功能一致,所以直接內(nèi)置。

實(shí)現(xiàn)代碼如下:

genPagination() {
  return (
    <div class="pagination-wrap">
      <el-pagination
        layout="total,prev,pager,next,jumper"
        current-page={this.current}
        page-size={this.pageSize}
        total={this.total}
        {...{
          on: { 'current-change': this.handleCurrentChange },
        }}
      ></el-pagination>
    </div>
  );
}

最后附完整代碼和demo:

<script>
export default {
  name: 'TableTemplate',
  props: {
    data: {
      type: Array,
      default: () => [],
      required: true,
    },
    headers: {
      type: Array,
      default: () => [],
      required: true,
    },
    current: {
      type: Number,
      default: 1,
    },
    pageSize: {
      type: Number,
      default: 10,
    },
    total: {
      type: Number,
      default: 0,
    },
    noSearchBar: Boolean,
    showAddBtn: Boolean,
  },
  mounted() {
    this.$nextTick(() => {
      this.$emit('search');
    });
  },
  methods: {
    genSearchBar() {
      if (this.noSearchBar || !this.$scopedSlots.searchBar) return '';
      return (
        <el-form class="seatch-form" inline={true} label-width="100">
          {this.$scopedSlots.searchBar()}
          <el-button
            class="filter-item"
            icon="el-icon-search"
            type="primary"
            onClick={this.handleSearchBtnClick}
          >
            查詢
          </el-button>
          <el-button
            class="filter-item"
            icon="el-icon-refresh"
            onClick={this.handleResetBtnClick}
          >
            重置
          </el-button>
          <el-button
            class="filter-item"
            icon="el-icon-plus"
            type="primary"
            v-show={this.showAddBtn}
            onClick={this.handleAddBtnClick}
          >
            新增
          </el-button>
        </el-form>
      );
    },
    genTableSlot(h) {
      let customeColumns = this.$scopedSlots.tableColumn
        ? this.$scopedSlots.tableColumn()
        : [];
      return this.headers.map((item) => {
        // 根據(jù)item.prop判斷是否使用傳入的插槽內(nèi)容
        let foundItem = customeColumns.find(
          (ele) =>
            ele.componentOptions &&
            ele.componentOptions.propsData.prop === item.prop
        );
        return foundItem
          ? foundItem
          : h('el-table-column', {
             props: {
               ...item,
             },
             scopedSlots: {
               default: (props) => {
                 let filter = this.$options.filters[
                   item.filter
                 ];
                 let itemValue = props.row[item.prop];
                 return h(
                   'span',
                   filter ? filter(itemValue) : itemValue
                 );
               },
             },
           });
      });
    },
    genTable(h) {
      return h(
        'el-table',
        {
          ref: 'tableRef',
          props: {
            ...this.$attrs,
            data: this.data,
          },
          on: {
            'selection-change': (val) => {
              this.$emit('selection-change', val);
            },
          },
        },
        [...this.genTableSlot(h)]
      );
    },
    genPagination() {
      return (
        <div class="pagination-wrap">
          <el-pagination
            layout="total,prev,pager,next,jumper"
            current-page={this.current}
            page-size={this.pageSize}
            total={this.total}
            {...{
              on: { 'current-change': this.handleCurrentChange },
            }}
          ></el-pagination>
        </div>
      );
    },
    resetPagination() {
      this.$emit('update:current', 1);
    },
    handleCurrentChange(val) {
      this.$emit('update:current', val);
      this.$emit('search');
    },
    handleSearchBtnClick() {
      this.$emit('search');
    },
    handleResetBtnClick() {
      this.resetPagination();
      this.$emit('reset');
    },
    handleAddBtnClick() {
      this.$emit('add');
    },
    getTableRef() {
      return this.$refs.tableRef;
    },
  },
  render(h) {
    return (
      <div>
        {this.genSearchBar()}
        {this.genTable(h)}
        {this.genPagination()}
      </div>
    );
  },
};
</script>

<style scoped>
.seatch-form {
  text-align: left;
}
.pagination-wrap {
  margin-top: 20px;
  text-align: right;
}
</style>

Demo:

<template>
  <div>
    <table-template
      border
      :headers="headers"
      :data="tableData"
      :current.sync="current"
      :total="total"
      ref="tableTemplate"
      showAddBtn
      @search="handleSearch"
      @reset="handleReset"
      @add="handleAdd"
      @selection-change="handleSelectionChange"
    >
      <template #searchBar>
        <el-form-item label="姓名:" prop="title">
          <el-input class="filter-item" v-model="searchForm.title" ></el-input>
        </el-form-item>
      </template>
      <template #tableColumn>
        <el-table-column
          prop="selection"
          type="selection"
          width="55"
        ></el-table-column>
        <el-table-column prop="test" label="姓名" width="180">
          <template slot-scope="scope">
            <el-popover trigger="hover" placement="top">
              <p>姓名:{{ scope.row.name }}</p>
              <p>住址:{{ scope.row.address }}</p>
              <div slot="reference" class="name-wrapper">
                <el-tag size="medium">{{scope.row.name}}</el-tag>
              </div>
            </el-popover>
          </template>
        </el-table-column>
      </template>
    </table-template>
  </div>
</template>

<script>
import TableTemplate from './TableTemplate';
export default {
  name: 'Demo',
  components: {
    TableTemplate,
  },
  data() {
    return {
      current: 1,
      total: 100,
      headers: [
        {
          prop: 'selection',
        },
        {
          label: '姓名',
          prop: 'name',
          width: '100',
        },
        {
          label: '年齡',
          prop: 'year',
        },
        {
          label: '性別',
          prop: 'sex',
          width: 'sexFilter',
        },
        {
          prop: 'test',
        },
      ],
      tableData: [
        {
          name: 'curry',
          year: 18,
          sex: 'female',
          address: '天安門',
        },
      ],
      searchForm: {
        title: '',
      },
    };
  },
  methods: {
    handleSearch() {
      console.log(this.current);
    },
    handleReset() {
      this.searchForm = {
        title: '',
      };
    },
    handleAdd() {
      console.log('添加');
    },
    handleSelectionChange(val) {
      console.log(val);
    },
    getTableRef() {
      console.log(this.$refs.tableTemplate.getTableRef());
    },
  },
};
</script>

看完上述內(nèi)容,你們對使用element-ui怎么封裝一個Table模板組件有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

網(wǎng)站標(biāo)題:使用element-ui怎么封裝一個Table模板組件-創(chuàng)新互聯(lián)
分享地址:http://muchs.cn/article24/dpsece.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、App開發(fā)商城網(wǎng)站、定制網(wǎng)站、微信公眾號網(wǎng)頁設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)