­

在Vue前端介面中,幾種數據表格的展示處理,以及表格編輯錄入處理操作。

 在Vue前端項目中,我這裡主要是基於Vue+Element的開發,大多數情況下,我們利用Element的表格組件就可以滿足大多數情況的要求,本篇隨筆針對表格的展示和編輯處理,綜合性的介紹幾款表格組件的展示和處理效果,其中包括Element的el-table組件,以及其他第三方類組件,如vue-easytable、vue-willtable,以及vxe-table,針對性的對比相關的差異。

1、el-table表格組件

這個是Element的表格組件,使用參考地址如下://element.eleme.cn/#/zh-CN/component/table
這個表格組件也是非常好用的展示數據的組件,提供了很多屬性設置,表格列的模板定義可以進行各種各樣的轉義和處理,是我們使用Element組件經常用到的組件之一。
簡單的介面效果如下所示。

 它的簡單介面程式碼如下所示,主要就是提供列的定義。

<template>
  <el-table :data="tableData" stripe style="width: 100%">
  <el-table-column prop="date"  label="日期"  width="180"> </el-table-column>
    <el-table-column prop="name" label="姓名" width="180"> </el-table-column>
    <el-table-column prop="address" label="地址"> </el-table-column>
  </el-table>
</template>

而數據這是一個對象集合,裡面對應各種屬性記錄,如下所示。

<script>
  export default {
    data() {
      return {
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀區金沙江路 1518 弄'
        }, {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀區金沙江路 1517 弄'
        }, {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀區金沙江路 1519 弄'
        }, {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀區金沙江路 1516 弄'
        }]
      }
    }
  }
</script>

不過一般實際使用的表格比這個會複雜很多,會在列之中提供很多轉義資訊展示,如下介面效果所示

或者

 

  我們來看看錶格頭部和表格列的相關定義來進行解析。

<el-table v-loading="listLoading" :data="list" border fit stripe highlight-current-row
          :header-cell-style="{background:'#eef1f6',color:'#606266'}" @selection-change="selectionChange"
          @row-dblclick="rowDbclick" @sort-change="sortChange">

listLoading用來 展示/隱藏 載入中的狀態

list則是提供給表格數據處理的數據源

selectionChange這是選中/取消勾選框的事件觸發

rowDbclick是雙擊表格行出現的事件響應

sortChange是排序表頭出現的事件處理

另外,表格數據往往涉及到分頁資訊,那麼必須和分頁控制項一起使用

        <!--分頁部分 -->
        <div class="block" style="height:70px;">
          <el-pagination :current-page="pageinfo.pageindex" :page-size="pageinfo.pagesize" :total="pageinfo.total"
            :page-sizes="[10,20,30,40]" layout="total, sizes, prev, pager, next" @size-change="sizeChange"
            @current-change="currentChange" />
        </div>

其中分頁組件中涉及到pageinfo對象,包括當前頁碼和每頁的數據記錄數量,以及對每頁數據大小變化事件sizeChange、頁碼變化的事件currentChange的處理。

因此我們在<script>中定義相關的變數和方法。

export default {
  components: {}, // 常見組件已經在main.js中掛載
  data () {
    return {
      listLoading: false, // 列表載入狀態
      list: [], // 頁面列表數據
      pageinfo: {// 分頁條件
        pageindex: 1,
        pagesize: 20,
        total: 0
      },
      listSelection: [], // 選中記錄
      sorting: null, // 排序條件

獲取數據的事件getlist中,我們主要就是根據條件獲取數據記錄,並賦值給list對象即可。

 而其他相應的事件如下定義所示

    search () { // 查詢列表處理
      this.pageinfo.pageindex = 1;// 重置為第一頁
      this.searchForm.pid = null;// 重置選擇類型
      this.getlist()
    },
    resetSeachForm (formName) { // 重置查詢條件處理
      this.$refs[formName].resetFields();
      this.search()
    },
    sortChange ({ column, prop, order }) {
      var direction = (order === 'ascending') ? ' ASC' : ' DESC'
      this.sorting = !this.isEmpty(prop) ? (prop + direction) : null
      this.getlist()
    },
    sizeChange (val) { // 頁面大小變化處理
      // console.log(`每頁 ${val} 條`);
      this.pageinfo.pagesize = val;
      this.getlist()
    },
    currentChange (val) { // 頁碼變化處理
      // console.log(`當前頁: ${val}`);
      this.pageinfo.pageindex = val;
      this.getlist()
    },
    selectionChange (val) { // 選中記錄
      this.listSelection = val;
    },
    rowDbclick (row, column) { // 列表單擊處理
      var id = row.id
      this.showView(id);
    },

這樣我們就是實現了對數據的分頁處理,和相關的事件處理。剩下的就是對記錄列內容的轉義處理了,這個通過HTML的程式碼進行處理即可。

常規的內容處理如下所示。

<el-table-column align="center" label="名稱" sortable="custom" prop="name" min-width="150">
   <template slot-scope="scope">
        {{ scope.row.name }}
   </template>
</el-table-column>

如果我們需要進行轉義,在這裡面處理判斷就可以了,非常方便。

  <el-table-column align="center" label="可見" sortable="custom" prop="visible" width="80">
    <template slot-scope="scope">
      <el-tag v-if="scope.row.visible" type="success" effect="dark">可見</el-tag>
      <el-tag v-else type="danger" effect="dark">隱藏</el-tag>
    </template>
  </el-table-column>

或者通過formater的函數進行內容的轉義處理。

<el-table-column align="center" label="創建時間" width="160" sortable="custom" prop="createTime"  :formatter="timeFormat" />

也可以使用filter進行內容轉義

  <el-table-column align="center" label="商品類型" width="120" prop="ProductType">
    <template slot-scope="scope">
      <el-tag type="danger">  {{ scope.row.ProductType | productTypeFilter }}</el-tag>
    </template>
  </el-table-column>

如果我們需要添加表格列的操作處理,那麼添加對應的按鈕即可,通過獲取對應記錄的標識,來進行相關記錄的操作即可。

  <!--表格行操作按鈕 -->
  <el-table-column align="center" label="操作" width="110">
    <template scope="scope">
      <el-row>
        <el-button-group>
          <el-tooltip effect="light" content="查看" placement="top-start">
            <el-button icon="el-icon-search" type="success" circle size="mini"
              @click="showView(scope.row.id)" />
          </el-tooltip>
          <el-tooltip effect="light" content="編輯" placement="top-start">
            <el-button icon="el-icon-edit" type="primary" circle size="mini" @click="showEdit(scope.row.id)" />
          </el-tooltip>
          <el-tooltip effect="light" content="刪除" placement="top-start">
            <el-button icon="el-icon-delete" type="danger" circle size="mini"
              @click="showDelete(scope.row.id)" />
          </el-tooltip>
        </el-button-group>
      </el-row>
    </template>
  </el-table-column>

Element的表格組件功能雖然很好,不過它的特點是展示處理,並不是很適合進行直接內容的編輯處理,有些人通過變數標識模板的方式控制編輯介面的展示,不過總體太複雜,不方便使用。

 

2、vue-easytable表格組件

vue-easytable表格組件地址:
npm安裝:npm install vue-easytable -S
這個組件相對於Element的表格el-table來說,它的HTML程式碼比較少,適用於簡單快捷的表格數據展示。
簡單使用程式碼如下所示
 <ve-table :columns="columns" :table-data="tableData" />

一般它的使用程式碼如下所示(配合分頁數據展示)

    <ve-table row-key-field-name="id" :checkbox-option="checkboxOption" :columns="columns" :table-data="list"
      :fixed-header="true" :border-around="true" :border-x="true" :border-y="true" />

    <!--分頁部分 -->
    <div class="block" style="height:70px;">
      <el-pagination :current-page="pageinfo.pageindex" :page-size="pageinfo.pagesize" :total="pageinfo.total"
        :page-sizes="[10,20,30,40]" layout="total, sizes, prev, pager, next" @size-change="sizeChange"
        @current-change="currentChange" />

常見的介面效果如下所示

 一般我們需要在JS中定義列的資訊,它的類型可以是expand、checkbox、radio幾種之一,默認是字元串方式。

當前列類型: “expand”:行展開;”checkbox”:行多選;”radio”:行單選

      columns: [// 表列定義
        {
          field: '',
          key: 'a',
          type: 'checkbox',
          title: '',
          width: 50,
          align: 'center'
        },
        {
          field: 'name',
          key: 'name',
          title: '姓名',
          width: 120,
          columnAlign: 'center'
        },

這個列的定義除了field外,還需要一個Key的標識,不能為空,一般保留位field的值即可。

如果我們需要進行內容的轉義處理,可以使用 renderBodyCell 函數進行轉義處理,如下所示。

        {
          field: 'sex',
          key: 'sex',
          title: '性別',
          width: 120,
          columnAlign: 'center',
          renderBodyCell: ({ row, column, rowIndex }, h) => {
            const text = row[column.field];
            // return <input style="width:100%" value={text}></input>;
            let html = null
            if (text === '男') {
              html = <el-tag type='primary'>{text}</el-tag>
            } else {
              html = <el-tag type='success'>{text}</el-tag>
            }
            return (
              <div>
                {html}
              </div>
            )
          }
        },

數據的處理,和我們前面介紹的類似,就是通過分頁條件的方式進行查詢分頁,獲得數據後賦值給對應列表即可。

      // 獲取列表,綁定到模型上,並修改分頁數量
      this.listLoading = true
      testUser.GetAll(param).then(data => {
        console.log(data.result.items)

        this.list = data.result.items
        this.pageinfo.total = data.result.totalCount
        this.listLoading = false
      })

通過 row-key-field-name=”id” :checkbox-option=”checkboxOption” 程式碼的處理,可以實現選中記錄的操作。

  checkboxOption: {
    // row select事件
    selectedRowChange: ({ row, isSelected, selectedRowKeys }) => {
      console.log(row, isSelected, selectedRowKeys);
    },
    // selected all事件
    selectedAllChange: ({ isSelected, selectedRowKeys }) => {
      console.log(isSelected, selectedRowKeys);
    }
  },

這個表格組件也主要是進行展示,沒有直接編輯的處理操作,不過它的特點是快速展示數據,轉義的話操作起來會費勁一些,它主要就是通過jsx的方式進行轉義處理的,感覺沒有在HTML上直接判斷的快捷明了。

 

3、vue-willtable表格組件(可直接編輯)

 以上兩個表格組件,都沒有涉及到編輯的操作,有時候我們在一些表格中希望給客戶直接錄入數據的場景。
如果採用el-table的方式來處理,非常不直觀,也不易處理,因此引入第三方組件的方式來實現數據的直接錄入就比較好 了。

vue-willtable表格組件地址://github.com/KevinMint55/vue-willtable

官方案例介面效果如下所示。

表格提供日期,數值、下拉列表,字元串等幾種常見方式的錄入。

 

 

總體上錄入沒有什麼問題,不過對於組件的更新好像有時候有些問題,畢竟github上星星不是很多的項目。

我在這個基礎上進行了案例的測試,介面效果如下所示。

主從表展示介面效果

 

 以及表格查詢分頁處理和錄入介面效果

    <div class="willtable_wrapper">
      <vue-willtable ref="table" v-model="list" :columns="columns" :row-height="38" :cell-class-name="cellClassName" />
    </div>

欄位定義的JS程式碼如下所示。

 獲取數據的JS程式碼如下所示

  // 獲取列表,綁定到模型上,並修改分頁數量
  this.listLoading = true
  testUser.GetAll(param).then(data => {
    this.$refs.table.setData(data.result.items)

    this.pageinfo.total = data.result.totalCount
    this.listLoading = false
  })

不過分頁的話,切換頁面大小會導致刷新顯示有些問題 ,部分空白,首次顯示倒是沒有問題。

 

4、vxe-table表格組件(可直接編輯)

vxe-table是github上星星超過4k+的開源組件,這個表格不論是展示數據,以及編輯的處理,都堪稱大能之作,非常方便強大。

vxe-table地址:

//xuliangzhan_admin.gitee.io/vxe-table/#/table/start/install

//github.com/x-extends/vxe-table

我們來看看它的常規使用程式碼,以及介面效果

 如果需要錄入新記錄,通事件處理添加一個行即可。 

 

 vxe-table的使用HTML程式碼和Element的el-table類似,通過HTML聲明的方式進行定義,如下所示。

<vxe-table ref="xTable" border show-overflow keep-source resizable show-overflow :data="list"
  :edit-config="{trigger: 'click', mode: 'row', showStatus: true}">
  <vxe-column type="seq" width="60" />
  <vxe-column field="name" title="姓名" :edit-render="{name: 'input', attrs: {type: 'text'}}" />

  <vxe-column field="sex" title="性別" :edit-render="{name: '$select', options: sexList}" />

  <vxe-column field="emailAddress" title="郵件地址"
    :edit-render="{name: 'input', attrs: {type: 'text', placeholder: '請輸入郵件地址'}}" />

  <vxe-column field="marriage" title="婚姻狀況"
    :edit-render="{name: '$select', options: marriageList, props: {multiple: false}}" />

  <vxe-column field="status" title="狀態"
    :edit-render="{name: '$select', options: StatusList, props: {multiple: false}}" />

  <vxe-column field="height" title="身高" :edit-render="{name: '$input', props: {type: 'float', digits: 2}}" />

  <vxe-column field="birthDate" title="出生日期"
    :edit-render="{name: '$input', props: {type: 'date', placeholder: '請選擇日期'}}" :formatter="formatDate" />
</vxe-table>

而數據的獲取展示方式,和上面程式碼操作一樣

      // 獲取列表,綁定到模型上,並修改分頁數量
      this.listLoading = true
      testUser.GetAll(param).then(data => {
        console.log(data.result.items)

        this.list = data.result.items
        this.pageinfo.total = data.result.totalCount
        this.listLoading = false
      })

其實我們主要關注它的數據的新增,以及保存處理即可,插入或者移除記錄的處理如下程式碼所示。

   async insertEvent () {
      const $table = this.$refs.xTable
      const newRecord = {}
      const { row: newRow } = await $table.insert(newRecord)
      await $table.setActiveRow(newRow)
    },
    async removeSelectEvent () {
      const $table = this.$refs.xTable
      await $table.removeCheckboxRow()
    },
    async removeRowEvent (row) {
      const $table = this.$refs.xTable
      await $table.remove(row)
    },

如果是保存,那麼需要獲取數據記錄的更新、刪除、新增幾個集合的情況,然後統一通過後端進行辨別處理即可。

    async saveEvent () {
      const $table = this.$refs.xTable
      const { insertRecords, removeRecords, updateRecords } = $table.getRecordset()
      if (insertRecords.length <= 0 && removeRecords.length <= 0 && updateRecords.length <= 0) {
        this.msgSuccess('數據未改動!')
        return
      }
      const errMap = await $table.validate().catch(errMap => errMap)
      if (errMap) {
        return
      }
      this.listLoading = true
      try {
        const body = { insertRecords, removeRecords, updateRecords }
        console.log(body)
        // /await XEAjax.post('//api.xuliangzhan.com:10443/demo/api/pub/save', body)
        // await this.loadList()
        this.msgSuccess(`操作成功,新增 ${insertRecords.length} 條,更新 ${updateRecords.length} 條,刪除 ${removeRecords.length} 條`)
      } catch (e) {
        if (e && e.message) {
          this.msgSuccess(e.message)
        }
      }
      this.listLoading = false
    },

通過引用對象的 getRecordset 我們可以獲得相關新增、更新、刪除的集合,然後通過自己的邏輯處理數據即可。

 

該表格組件提供了很多方便的處理案例,我們可以通過學習方式進行參考即可。

以上就是幾款表格組件的效果,對比它們,一般來說,我們還是傾向於使用el-table的內置表格組件來展示數據,而且也可以通過我們的程式碼生成工具Database2sharp進行vue介面的快速生成,然後微調即可,而對於數據直接編輯的處理,則建議通過使用vxe-table的組件的方式進行處理,它提供了非常多強大的功能,可以滿足我們直接錄入數據的處理操作。