您好,登錄后才能下訂單哦!
這篇文章主要講解了“elementUI el-table二次封裝的方法是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“elementUI el-table二次封裝的方法是什么”吧!
index.vue為父級(jí)頁面
yxt-table.vue為表格組件
因?yàn)楸砀竦臄?shù)據(jù)一般都比較簡單,就是根據(jù)搜索條件,調(diào)用接口請(qǐng)求一個(gè)到列表,然后將列表數(shù)據(jù)一一展示到表格上,再對(duì)特定的列進(jìn)行一些過濾轉(zhuǎn)化等個(gè)性化操作。但是萬變不離其宗,這個(gè)步驟基本每個(gè)表格都要進(jìn)行一遍,所以考慮到通用性(其實(shí)是為了偷懶),將請(qǐng)求接口獲取數(shù)據(jù)這一步放在組件里面實(shí)現(xiàn)。
created () { this.getData() }, methods: { getData () { const fun = this.apiUrl fun().then(res => { this.tableData = res[this.otherConfig.list] || [] this.tableTotal = res.pageInfo?.total || 0 }) } }
組件接收一個(gè)數(shù)組作為自定義列
tableColumn: [ { prop: 'name', label: '名稱' }, { prop: 'code', label: '編碼' }, { prop: 'status', label: '狀態(tài)' } ]
index.vue
<!-- index.vue --> <template> <div> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn"></yxt-table> </div> </template> <!-- index.vue --> <script> import yxtTable from './yxt-table.vue' import { yxtTableList } from 'https/yxtDemo.js' export default { name: 'yxtDemoTable', components: { yxtTable }, data () { return { yxtTableList, tableColumn: [ { prop: 'name', label: '名稱' }, { prop: 'code', label: '編碼' }, { prop: 'status', label: '狀態(tài)' } ] } } } </script>
yxt-table.vue
<!-- yxt-table.vue --> <template> <div> <el-table :data="tableData"> <el-table-column v-for="item in tableColumn" :key="item.prop" :prop="item.prop" :label="item.label"></el-table-column> </el-table> </div> </template> <!-- yxt-table.vue --> <script> export default { name: 'yxtTable', props: { apiUrl: { // 列表接口(必填) type: Function, required: true }, tableColumn: { // 自定義列配置 type: Array, default: () => [] }, otherConfig: { // type: Object, default: () => { return { list: 'list' } } } }, data () { return { tableData: [] } }, created () { this.getData() }, methods: { getData () { const fun = this.apiUrl fun().then(res => { this.tableData = res[this.otherConfig.list] || [] this.tableTotal = res.pageInfo?.total || 0 }) } } } </script>
至此,一個(gè)表格可以實(shí)現(xiàn)了
1、otherConfig說明
由于我們的接口請(qǐng)求放在組件里面了,但是我們對(duì)接的接口可能由于業(yè)務(wù)的不同項(xiàng)目組的不同開發(fā)人員的不同,而導(dǎo)致接口返回的列表的字段名不同,這里通過傳參的形式做一下兼容
2、上面這樣只能實(shí)現(xiàn)簡單的展示功能,還有些數(shù)據(jù)比如 狀態(tài)1 需要轉(zhuǎn)化為打卡成功,狀態(tài)0 需要轉(zhuǎn)化為打卡失敗進(jìn)行顯示,這類需求可以通過filter進(jìn)行轉(zhuǎn)化
<!-- yxt-table.vue --> <el-table-column v-for="item in tableColumn" :key="item.prop" :prop="item.prop" :label="item.label"> <template v-slot:default="scope"> <div v-if="item.dictCode"> {{ scope.row[item.prop] | filterStatus(dict[item.dictCode]) }} </div> <div v-else> {{ scope.row[item.prop] }} </div> </template> </el-table-column> props: { dict: { // 全部字典 type: Object, default: () => {} } }, filters: { filterStatus (value, array, code = 'code', name = 'name') { if (!value && value !== 0) { // 要把0摘出來,一般0都是正常的數(shù)據(jù),所以不能只用 !value return '' } const find = array.find(e => (e[code] === value.toString()) || (e[code] === +value)) // 字符型數(shù)值型都得匹配 if (find) { return find[name] } else { // 沒有匹配的就原樣返回 return value } } },
<!-- index.vue --> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :dict="dict"></yxt-table> data () { return { tableColumn: [ { prop: 'name', label: '名稱' }, { prop: 'code', label: '編碼' }, { prop: 'status', label: '狀態(tài)', dictCode: 'status' } ], dict: { status: [ { code: 0, name: '打卡失敗' }, { code: 1, name: '打卡成功' } ] } } }
這里dict設(shè)置為對(duì)象的原因是為了裝進(jìn)更多字典
3、思考一下,如果要在表格中展示這樣的自定義圖標(biāo)怎么辦?
使用插槽slot,在tableColumn里面設(shè)置某行屬性的slot為true,改造el-table-column如下:
<!-- yxt-table.vue --> <el-table-column v-for="(item, index) in tableColumn" :key="index" :prop="item.prop" :label="item.label"> <template v-if="item.slot" v-slot:default="scope"> <slot :name="item.prop" :row="scope.row" :index="scope.$index"></slot> </template> <template v-else v-slot:default="scope"> <div v-if="item.dictCode"> {{ scope.row[item.prop] | filterStatus(dict[item.dictCode]) }} </div> <div v-else> {{ scope.row[item.prop] }} </div> </template> </el-table-column>
<!-- index.vue --> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :otherConfig="otherConfig" :dict="dict"> <template v-slot:icon="{row, index}"> <i :class="row.status ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i> </template> </yxt-table> data () { return { tableColumn: [ { prop: 'name', label: '名稱' }, { prop: 'code', label: '編碼' }, { prop: 'status', label: '狀態(tài)', dictCode: 'status' }, { prop: 'icon', label: '圖標(biāo)', slot: true } ] } }
4、在實(shí)際項(xiàng)目中,除了字典轉(zhuǎn)化,還有一些比較定制化的展示需求,這個(gè)可以通過傳入一個(gè)函數(shù)format進(jìn)行計(jì)算,然后在這個(gè)方法里面將最后的計(jì)算結(jié)果return
<!-- yxt-table.vue --> <el-table-column v-for="(item, index) in tableColumn" :key="index" :prop="item.prop" :label="item.label"> <template v-if="item.slot" v-slot:default="scope"> <slot :name="item.prop" :row="scope.row" :index="scope.$index"></slot> </template> <template v-else v-slot:default="scope"> <div v-if="item.dictCode"> {{ scope.row[item.prop] | filterStatus(dict[item.dictCode]) }} </div> <div v-else-if="item.format"> {{ item.format(scope.row) }} </div> <div v-else> {{ scope.row[item.prop] }} </div> </template> </el-table-column>
<!-- index.vue --> data () { return { tableColumn: [ { prop: 'name', label: '名稱' }, { prop: 'code', label: '編碼' }, { prop: 'status', label: '狀態(tài)', dictCode: 'status' }, { prop: 'icon', label: '圖標(biāo)', slot: true }, { prop: 'phone', label: '電話號(hào)碼', format: (row) => { return `${row.name}-${row.code}(${row.phone})` } } ] } }
5、表格一般還有批量操作,所以需要多選和單選以及針對(duì)特定場景設(shè)置禁選
yxt-table.vue
<!-- yxt-table.vue --> <template> <div class="yxt-table"> <!-- 批量操作按鈕,因?yàn)槊總€(gè)需求不同,批量操作的功能也不同,所以這里只放一個(gè)插槽,不設(shè)置默認(rèn)內(nèi)容,所有按鈕均在父級(jí)設(shè)置 --> <div class="multiple-operation"> <slot name="multiple-operation" :selectionData="selectionData"></slot> </div> <!-- 頁面主表格 --> <el-table :data="tableData" :row-key="rowKey" @selection-change="selectionChange"> <!-- 可選框(多選) --> <el-table-column v-if="selection === 'multiple'" type="selection" align="center" width="55" :reserve-selection="rowKey ? true : false" :selectable="selectable"/> <!-- 可選框(單選) --> <el-table-column v-else-if="selection === 'single'" align="center" width="30"> <template v-slot:default="scope"> <el-radio v-model="selectionRadio" :label="scope.$index" :disabled="selectable ? !selectable(scope.row) : false" @change="selectionChangeSingle(scope.row)"> {{ '' }} </el-radio> </template> </el-table-column> <el-table-column v-for="(item, index) in tableColumn" :key="index" :prop="item.prop" :label="item.label"> <template v-if="item.slot" v-slot:default="scope"> <slot :name="item.prop" :row="scope.row" :index="scope.$index"></slot> </template> <template v-else v-slot:default="scope"> <div v-if="item.dictCode"> {{ scope.row[item.prop] | filterStatus(dict[item.dictCode]) }} </div> <div v-else-if="item.format"> {{ item.format(scope.row) }} </div> <div v-else> {{ scope.row[item.prop] }} </div> </template> </el-table-column> </el-table> </div> </template> <!-- yxt-table.vue --> <script> export default { name: 'yxtTable', props: { apiUrl: { // 列表接口(必填) type: Function, required: true }, tableColumn: { // 自定義列配置 type: Array, default: () => [] }, otherConfig: { // 其他配置 type: Object, default: () => { return { list: 'list' // 接口返回?cái)?shù)據(jù)的列表字段的字段名(因?yàn)樵诮M件里面調(diào)接口,可能不同業(yè)務(wù)不同項(xiàng)目組不同一個(gè)開發(fā)者返回給前端的參數(shù)名不一致,這里進(jìn)行兼容) } } }, dict: { // 全部字典 type: [Array, Object], default: () => [] }, selection: { // 是否顯示可選框(多選-multiple 、單選-single ) type: String }, selectable: { // 當(dāng)前行是否可選擇 type: Function }, rowKey: { // 表格唯一key(適用于分頁多選表格,保留之前的選擇,不傳則為單頁選擇) type: [Number, String, Function], default: '' } }, filters: { filterStatus (value, array, code = 'code', name = 'name') { if (!value && value !== 0) { // 要把0摘出來,一般0都是正常的數(shù)據(jù),所以不能只用 !value return '' } const find = array.find(e => (e[code] === value.toString()) || (e[code] === +value)) // 字符型數(shù)值型都得匹配 if (find) { return find[name] } else { // 沒有匹配的就原樣返回 return value } } }, data () { return { tableData: [], tableTotal: 0, selectionRadio: '', selectionData: [] } }, created () { this.getData() }, methods: { getData () { const fun = this.apiUrl fun().then(res => { this.tableData = res[this.otherConfig.list] || [] this.tableTotal = res.pageInfo?.total || 0 }) }, // 多選,選擇行數(shù)據(jù)change selectionChange (selection) { this.selectionData = selection }, // 單選,選擇行數(shù)據(jù)change selectionChangeSingle (selection) { this.selectionData = [selection] } } } </script> <style scoped lang="scss"> .yxt-table { margin: 30px; .multiple-operation { margin-bottom: 10px; } } </style>
index.vue
<!-- index.vue --> <template> <div> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :otherConfig="otherConfig" :dict="dict" selection="multiple" :selectable="isSelectable"> <!-- 圖標(biāo)插槽 --> <template v-slot:icon="{row, index}"> <i :class="row.status ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i> </template> <!-- 批量操作按鈕插槽 --> <template v-slot:multiple-operation="{selectionData}"> <el-button type="primary" size="small" @click="handleClick1(selectionData)">批量操作1</el-button> <el-button type="success" size="small" @click="handleClick2(selectionData)">批量操作2</el-button> </template> </yxt-table> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :otherConfig="otherConfig" :dict="dict" selection="single" :selectable="isSelectable"> <!-- 圖標(biāo)插槽 --> <template v-slot:icon="{row, index}"> <i :class="row.status ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i> </template> <!-- 批量操作按鈕插槽 --> <template v-slot:multiple-operation="{selectionData}"> <el-button type="primary" size="small" @click="handleClick1(selectionData)">單選操作</el-button> </template> </yxt-table> </div> </template> <!-- index.vue --> <script> import yxtTable from './yxt-table.vue' import { yxtTableList } from 'https/yxtDemo.js' export default { name: 'yxtDemoTable', components: { yxtTable }, data () { return { yxtTableList, tableColumn: [ { prop: 'name', label: '名稱' }, { prop: 'code', label: '編碼' }, { prop: 'status', label: '狀態(tài)', dictCode: 'status' }, { prop: 'icon', label: '圖標(biāo)', slot: true }, { prop: 'phone', label: '電話號(hào)碼', format: (row) => { return `${row.name}-${row.code}(${row.phone})` } } ], tableConfig: { stripe: 'stripe', border: 'border', height: '200', maxHeight: '200', showHeader: true }, otherConfig: { list: 'tasks' }, dict: { status: [ { code: 0, name: '打卡失敗' }, { code: 1, name: '打卡成功' } ] } } }, methods: { handleClick1 (selectionData) { console.log('1', selectionData) }, handleClick2 (selectionData) { console.log('2', selectionData) }, isSelectable (row) { return row.selectable !== 0 } } } </script> <style scoped lang="scss"> .el-icon-circle-check { font-size: 28px; color: #67C23A; } .el-icon-circle-close { font-size: 28px; color: #F00; } </style>
6、操作列
根據(jù)業(yè)務(wù)需求,可以在操作列設(shè)置幾個(gè)默認(rèn)按鈕,通過setupConfig設(shè)置開關(guān),如果有除了默認(rèn)按鈕之外的操作需求,再通過插槽slot進(jìn)行插入
<!-- yxt-table.vue --> <!-- 操作列 --> <el-table-column v-if="setupConfig.width !== 0" :fixed="setupConfig.fixed" :width="setupConfig.width" label="操作"> <template v-slot:default="scope"> <slot name="setup" :row="scope.row" :index="scope.$index"></slot> <!-- 查看 --> <el-button v-if="setupConfig.view" type="text" @click="setupEvents('view', scope.row)">查看</el-button> <!-- 編輯 --> <el-button v-if="setupConfig.edit" type="text" @click="setupEvents('edit', scope.row)">編輯</el-button> <!-- 刪除 --> <el-button v-if="setupConfig.del" type="text" @click="setupEvents('del', scope.row)">刪除</el-button> <!-- 操作日志 --> <el-button v-if="setupConfig.log" type="text" @click="setupEvents('log', scope.row)">操作日志</el-button> </template> </el-table-column> props: { setupConfig: { type: Object, default: () => { return { width: 'auto' } } } }, methods: { setupEvents (setupType, row) { // 操作列方法 查看/編輯/刪除/操作日志 this.$emit(setupType, row) } }
index.vue做相應(yīng)的處理,這里不貼代碼了
7、分頁
pagination控制是否需要分頁組件,如果不需要分頁則設(shè)置為false。根據(jù)業(yè)務(wù)需求,可傳入pageSizes控制條數(shù)下拉框的條數(shù)選項(xiàng)
<!-- yxt-table.vue --> <!-- 分頁 --> <el-pagination v-if="pagination" class="pagination tablePage" :pager-count="5" :page-sizes="pageSizes || [10, 20, 50, 100]" :total="tableTotal || 0" :page-size="pageInfo.pageSize || 10" :current-page="pageInfo.startPage || 1" layout="total, sizes, prev, pager, next, jumper" @size-change="sizeChange" @current-change="pageChange"></el-pagination> props: { pagination: { // 是否需要分頁,默認(rèn)需要 type: Boolean, default: true }, pageSizes: { type: Array } }, methods: { getData () { const fun = this.apiUrl const pageInfo = { // 分頁信息 pageSize: this.pageInfo.pageSize, startPage: this.pageInfo.startPage } let param = { // 其他的搜素條件 } if (this.pagination) { // 如果需要分頁,則傳分頁信息 param = { ...param, ...pageInfo } } fun(param).then(res => { this.tableData = res[this.otherConfig.list] || [] this.tableTotal = res.pageInfo?.total || 0 }) }, // 條數(shù)變化 sizeChange (size) { this.pageInfo.startPage = 1 this.pageInfo.pageSize = size this.getData() }, // 頁碼變化 pageChange (page) { this.pageInfo.startPage = page this.getData() } }
8、el-table還有一個(gè)展開行功能expand,根據(jù)業(yè)務(wù)需求,也可以加進(jìn)組件里
<!-- yxt-table.vue --> <!-- 展開行 --> <el-table-column v-if="expand" type="expand"> <template v-slot:default="scope"> <slot name="expand" :row="scope.row" :index="scope.$index"></slot> </template> </el-table-column> props: { expand: { // 是否展開行 type: Boolean, default: false } }
<!-- index.vue --> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :expand="true"> <template v-slot:expand="{row, index}"> <div> <p>序號(hào):{{index}}</p> <p>內(nèi)容:{{row}}</p> </div> </template> </yxt-table>
新增一個(gè)yxt-search.vue
<!-- yxt-search.vue --> <template> <div class="yxt-search"> <div v-for="(item,index) in searchConfig" :key="index" class="yxt-search-item"> <el-input v-if="item.type==='input'" v-model="searchModel[item.key]" size="medium" :clearable="item.clearable || true" :placeholder="item.placeholder || '請(qǐng)輸入'" :maxlength="item.maxlength"></el-input> <el-select v-if="item.type==='select'" v-model="searchModel[item.key]" size="medium" :clearable="item.clearable || true" :filterable="item.filterable || true" :disabled="item.disabled || false" :multiple="item.multiple || false" :allow-create="item.allowCreate" :placeholder="item.placeholder || '請(qǐng)選擇'"> <el-option v-for="(selectItem, selectIndex) in item.selectList" :key="selectIndex" :label="selectItem[item.listLabel]" :value="selectItem[item.listValue]"></el-option> </el-select> </div> <div v-if="searchConfig.length" class="yxt-search-button"> <el-button size="medium" type="primary" @click="search">搜索</el-button> <el-button size="medium" type="primary" plain @click="reset">重置</el-button> <!-- 其他的按鈕需求通過插槽傳入 --> <slot name="searchBtn" :searchData="searchModel"></slot> </div> </div> </template> <!-- yxt-search.vue --> <script> export default { name: 'yxtSearch', props: { searchConfig: { // 搜索條件配置項(xiàng) type: Array, required: true, default () { return [] } }, searchModel: { // 搜索條件綁定值 type: Object, required: true, default () { return {} } }, searchReset: { // 搜索條件默認(rèn)值重置值 type: Object } }, data () { return { } }, methods: { search () { this.$emit('search', this.searchModel) }, reset () { if (this.searchReset) { // 如果傳入有默認(rèn)值,則重置后為默認(rèn)值 Object.keys(this.searchModel).forEach((item) => { this.searchModel[item] = this.searchReset[item] }) } else { Object.keys(this.searchModel).forEach((item) => { this.searchModel[item] = '' }) } } } } </script> <style scoped lang="scss"> .yxt-search { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: flex-start; .yxt-search-item { flex: 1; margin: 0 10px 10px 0; width: calc((100% - 30px) / 4); // 這里的30px = (分布個(gè)數(shù)4-1)*間隙1px, 可以根據(jù)實(shí)際的分布個(gè)數(shù)和間隙區(qū)調(diào)整 min-width: calc((100% - 30px) / 4); max-width: calc((100% - 30px) / 4); &:nth-child(4n) { // 去除每行最后一個(gè)(第4n個(gè))的margin-right margin-right: 0; } } .yxt-search-button { margin: 0 0 10px 0; width: 100%; text-align: right; } } </style>
<!-- yxt-table.vue --> <yxt-search :searchConfig="searchConfig" :searchModel="searchModel" :searchReset="searchReset" @search="getData(1)"> <template v-slot:searchBtn="{searchData}"> <!-- 其他的按鈕需求通過插槽傳入 --> <slot name="searchBtn" :searchData="searchData"></slot> </template> </yxt-search> props: { searchConfig: { // 搜索條件配置項(xiàng) type: Array, default () { return [] } }, searchReset: { // 搜索條件默認(rèn)值重置值 type: Object } }, data () { return { searchModel: this.searchReset ? JSON.parse(JSON.stringify(this.searchReset)) : {} } }, methods: { getData (startPage) { if (startPage) { // 如果傳入值,則從改值的頁碼數(shù)開始 this.pageInfo.startPage = startPage } let param = { // 其他的搜素條件 ...this.searchModel } ... } }
<!-- index.vue --> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :searchConfig="searchConfig" :searchReset="searchReset"> <template v-slot:searchBtn="{searchData}"> <el-button size="medium" type="success" @click="handleClickExport(searchData)">導(dǎo)出</el-button> </template> </yxt-table> data () { return { searchConfig: [ { type: 'input', key: 'name' }, { type: 'input', key: 'code' }, { type: 'select', key: 'status', selectList: [ { code: 0, name: '打卡失敗' }, { code: 1, name: '打卡成功' } ], listLabel: 'name', listValue: 'code' } ], searchReset: { name: '張三', code: '', status: 1 } } }, methods: { handleClickExport (data) { console.log(data) } }
加載中:el-table 添加 v-loading="loading",getData里面,發(fā)送請(qǐng)求之前設(shè)置為true,獲得數(shù)據(jù)后設(shè)置為false
空數(shù)據(jù):通過插槽empty設(shè)置
index.vue
<!-- index.vue --> <template> <div> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :otherConfig="otherConfig" :dict="dict" selection="multiple" :selectable="isSelectable" :setupConfig="setupConfig" :searchConfig="searchConfig" :searchReset="searchReset" @view="view" @log="log"> <!-- 圖標(biāo)插槽 --> <template v-slot:icon="{row, index}"> <i :class="row.status ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i> </template> <!-- 批量操作按鈕插槽 --> <template v-slot:multiple-operation="{selectionData}"> <el-button type="primary" size="small" @click="handleClick1(selectionData)">批量操作1</el-button> <el-button type="success" size="small" @click="handleClick2(selectionData)">批量操作2</el-button> </template> <template v-slot:searchBtn="{searchData}"> <el-button size="medium" type="success" @click="handleClickExport(searchData)">導(dǎo)出</el-button> </template> </yxt-table> <yxt-table :apiUrl="yxtTableList" :tableColumn="tableColumn" :otherConfig="otherConfig" :dict="dict" selection="single" :selectable="isSelectable" :setupConfig="setupConfig2" :pagination="false" :expand="true" :emptyText="'沒有數(shù)據(jù)的展示文字'"> <!-- 圖標(biāo)插槽 --> <template v-slot:icon="{row, index}"> <i :class="row.status ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i> </template> <!-- 批量操作按鈕插槽 --> <template v-slot:multiple-operation="{selectionData}"> <el-button type="primary" size="small" @click="handleClick1(selectionData)">單選操作</el-button> </template> <template v-slot:expand="{row, index}"> <div> <p>序號(hào):{{index}}</p> <p>內(nèi)容:{{row}}</p> </div> </template> </yxt-table> </div> </template> <!-- index.vue --> <script> import yxtTable from './yxt-table.vue' import { yxtTableList } from 'https/yxtDemo.js' export default { name: 'yxtDemoTable', components: { yxtTable }, data () { return { yxtTableList, tableColumn: [ { prop: 'name', label: '名稱' }, { prop: 'code', label: '編碼' }, { prop: 'status', label: '狀態(tài)', dictCode: 'status' }, { prop: 'icon', label: '圖標(biāo)', slot: true }, { prop: 'phone', label: '電話號(hào)碼', format: (row) => { return `${row.name}-${row.code}(${row.phone})` } } ], tableConfig: { stripe: 'stripe', border: 'border', height: '200', maxHeight: '200', showHeader: true }, otherConfig: { list: 'tasks' }, setupConfig: { width: 100, view: true, log: true }, setupConfig2: { edit: true, del: true, log: true }, dict: { status: [ { code: 0, name: '打卡失敗' }, { code: 1, name: '打卡成功' } ] }, searchConfig: [ { type: 'input', key: 'name' }, { type: 'input', key: 'code' }, { type: 'select', key: 'status', selectList: [ { code: 0, name: '打卡失敗' }, { code: 1, name: '打卡成功' } ], listLabel: 'name', listValue: 'code' } ], searchReset: { name: '張三', code: '', status: 1 } } }, methods: { handleClick1 (selectionData) { console.log('1', selectionData) }, handleClick2 (selectionData) { console.log('2', selectionData) }, handleClickExport (data) { console.log(data) }, isSelectable (row) { return row.selectable !== 0 }, view (row) { console.log('view', row) }, log (row) { console.log('log', row) } } } </script> <style scoped lang="scss"> .el-icon-circle-check { font-size: 28px; color: #67C23A; } .el-icon-circle-close { font-size: 28px; color: #F00; } </style>
yxt-table.vue
<!-- yxt-table.vue --> <template> <div class="yxt-table"> <yxt-search :searchConfig="searchConfig" :searchModel="searchModel" :searchReset="searchReset" @search="getData(1)"> <template v-slot:searchBtn="{searchData}"> <!-- 其他的按鈕需求通過插槽傳入 --> <slot name="searchBtn" :searchData="searchData"></slot> </template> </yxt-search> <!-- 批量操作按鈕,因?yàn)槊總€(gè)需求不同,批量操作的功能也不同,所以這里只放一個(gè)插槽,不設(shè)置默認(rèn)內(nèi)容,所有按鈕均在父級(jí)設(shè)置 --> <div class="multiple-operation"> <slot name="multiple-operation" :selectionData="selectionData"></slot> </div> <!-- 頁面主表格 --> <el-table :data="tableData" :row-key="rowKey" v-loading="loading" @selection-change="selectionChange"> <!-- 可選框(多選) --> <el-table-column v-if="selection === 'multiple'" type="selection" align="center" width="55" :reserve-selection="rowKey ? true : false" :selectable="selectable"/> <!-- 可選框(單選) --> <el-table-column v-else-if="selection === 'single'" align="center" width="30"> <template v-slot:default="scope"> <el-radio v-model="selectionRadio" :label="scope.$index" :disabled="selectable ? !selectable(scope.row) : false" @change="selectionChangeSingle(scope.row)"> {{ '' }} </el-radio> </template> </el-table-column> <!-- 展開行 --> <el-table-column v-if="expand" type="expand"> <template v-slot:default="scope"> <slot name="expand" :row="scope.row" :index="scope.$index"></slot> </template> </el-table-column> <el-table-column v-for="(item, index) in tableColumn" :key="index" :prop="item.prop" :label="item.label"> <template v-if="item.slot" v-slot:default="scope"> <slot :name="item.prop" :row="scope.row" :index="scope.$index"></slot> </template> <template v-else v-slot:default="scope"> <div v-if="item.dictCode"> {{ scope.row[item.prop] | filterStatus(dict[item.dictCode]) }} </div> <div v-else-if="item.format"> {{ item.format(scope.row) }} </div> <div v-else> {{ scope.row[item.prop] }} </div> </template> </el-table-column> <!-- 操作列 --> <el-table-column v-if="setupConfig.width !== 0" :fixed="setupConfig.fixed" :width="setupConfig.width" label="操作"> <template v-slot:default="scope"> <slot name="setup" :row="scope.row" :index="scope.$index"></slot> <!-- 查看 --> <el-button v-if="setupConfig.view" type="text" @click="setupEvents('view', scope.row)">查看</el-button> <!-- 編輯 --> <el-button v-if="setupConfig.edit" type="text" @click="setupEvents('edit', scope.row)">編輯</el-button> <!-- 刪除 --> <el-button v-if="setupConfig.del" type="text" @click="setupEvents('del', scope.row)">刪除</el-button> <!-- 操作日志 --> <el-button v-if="setupConfig.log" type="text" @click="setupEvents('log', scope.row)">操作日志</el-button> </template> </el-table-column> <!-- 空狀態(tài) --> <template slot="empty"> <p>{{ emptyText }}</p> </template> </el-table> <!-- 分頁 --> <el-pagination v-if="pagination" class="pagination tablePage" :pager-count="5" :page-sizes="pageSizes || [10, 20, 50, 100]" :total="tableTotal || 0" :page-size="pageInfo.pageSize || 10" :current-page="pageInfo.startPage || 1" layout="total, sizes, prev, pager, next, jumper" @size-change="sizeChange" @current-change="pageChange"></el-pagination> </div> </template> <!-- yxt-table.vue --> <script> import yxtSearch from './yxt-search' export default { name: 'yxtTable', components: { yxtSearch }, props: { apiUrl: { // 列表接口(必填) type: Function, required: true }, tableColumn: { // 自定義列配置 type: Array, default: () => [] }, otherConfig: { // 其他配置 type: Object, default: () => { return { list: 'list' // 接口返回?cái)?shù)據(jù)的列表字段的字段名(因?yàn)樵诮M件里面調(diào)接口,可能不同業(yè)務(wù)不同項(xiàng)目組不同一個(gè)開發(fā)者返回給前端的參數(shù)名不一致,這里進(jìn)行兼容) } } }, dict: { // 全部字典 type: [Array, Object], default: () => [] }, selection: { // 是否顯示可選框(多選-multiple 、單選-single ) type: String }, selectable: { // 當(dāng)前行是否可選擇 type: Function }, rowKey: { // 表格唯一key(適用于分頁多選表格,保留之前的選擇,不傳則為單頁選擇) type: [Number, String, Function], default: '' }, setupConfig: { type: Object, default: () => { return { width: 'auto' } } }, pagination: { // 是否需要分頁,默認(rèn)需要 type: Boolean, default: true }, pageSizes: { // 分頁的下拉框選項(xiàng) type: Array }, expand: { // 是否展開行 type: Boolean, default: false }, searchConfig: { // 搜索條件配置項(xiàng) type: Array, default () { return [] } }, searchReset: { // 搜索條件默認(rèn)值重置值 type: Object }, emptyText: { type: String } }, filters: { filterStatus (value, array, code = 'code', name = 'name') { if (!value && value !== 0) { // 要把0摘出來,一般0都是正常的數(shù)據(jù),所以不能只用 !value return '' } const find = array.find(e => (e[code] === value.toString()) || (e[code] === +value)) // 字符型數(shù)值型都得匹配 if (find) { return find[name] } else { // 沒有匹配的就原樣返回 return value } } }, data () { return { loading: true, tableData: [], tableTotal: 0, pageInfo: { pageSize: 10, startPage: 1 }, selectionRadio: '', selectionData: [], searchModel: this.searchReset ? JSON.parse(JSON.stringify(this.searchReset)) : {} } }, created () { this.getData() }, methods: { getData (startPage) { if (startPage) { // 如果傳入值,則從改值的頁碼數(shù)開始 this.pageInfo.startPage = startPage } this.loading = true const fun = this.apiUrl const pageInfo = { // 分頁信息 pageSize: this.pageInfo.pageSize, startPage: this.pageInfo.startPage } let param = { // 其他的搜素條件 ...this.searchModel } if (this.pagination) { // 如果需要分頁,則傳分頁信息 param = { ...param, ...pageInfo } } fun(param).then(res => { setTimeout(() => { this.tableData = res[this.otherConfig.list] || [] this.tableTotal = res.pageInfo?.total || 0 this.loading = false }, 2000) }) }, // 多選,選擇行數(shù)據(jù)change selectionChange (selection) { this.selectionData = selection }, // 單選,選擇行數(shù)據(jù)change selectionChangeSingle (selection) { this.selectionData = [selection] }, // 操作列方法 查看/編輯/刪除/操作日志 setupEvents (setupType, row) { this.$emit(setupType, row) }, // 條數(shù)變化 sizeChange (size) { this.pageInfo.startPage = 1 this.pageInfo.pageSize = size this.getData() }, // 頁碼變化 pageChange (page) { this.pageInfo.startPage = page this.getData() } } } </script> <style scoped lang="scss"> .yxt-table { margin: 30px; .multiple-operation { margin-bottom: 10px; } } </style>
yxt-search.vue
<!-- yxt-search.vue --> <template> <div class="yxt-search"> <div v-for="(item,index) in searchConfig" :key="index" class="yxt-search-item"> <el-input v-if="item.type==='input'" v-model="searchModel[item.key]" size="medium" :clearable="item.clearable || true" :placeholder="item.placeholder || '請(qǐng)輸入'" :maxlength="item.maxlength"></el-input> <el-select v-if="item.type==='select'" v-model="searchModel[item.key]" size="medium" :clearable="item.clearable || true" :filterable="item.filterable || true" :disabled="item.disabled || false" :multiple="item.multiple || false" :allow-create="item.allowCreate" :placeholder="item.placeholder || '請(qǐng)選擇'"> <el-option v-for="(selectItem, selectIndex) in item.selectList" :key="selectIndex" :label="selectItem[item.listLabel]" :value="selectItem[item.listValue]"></el-option> </el-select> </div> <div v-if="searchConfig.length" class="yxt-search-button"> <el-button size="medium" type="primary" @click="search">搜索</el-button> <el-button size="medium" type="primary" plain @click="reset">重置</el-button> <!-- 其他的按鈕需求通過插槽傳入 --> <slot name="searchBtn" :searchData="searchModel"></slot> </div> </div> </template> <!-- yxt-search.vue --> <script> export default { name: 'yxtSearch', props: { searchConfig: { // 搜索條件配置項(xiàng) type: Array, required: true, default () { return [] } }, searchModel: { // 搜索條件綁定值 type: Object, required: true, default () { return {} } }, searchReset: { // 搜索條件默認(rèn)值重置值 type: Object } }, data () { return { } }, methods: { search () { this.$emit('search', this.searchModel) }, reset () { if (this.searchReset) { // 如果傳入有默認(rèn)值,則重置后為默認(rèn)值 Object.keys(this.searchModel).forEach((item) => { this.searchModel[item] = this.searchReset[item] }) } else { Object.keys(this.searchModel).forEach((item) => { this.searchModel[item] = '' }) } } } } </script> <style scoped lang="scss"> .yxt-search { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: flex-start; .yxt-search-item { flex: 1; margin: 0 10px 10px 0; width: calc((100% - 30px) / 4); // 這里的30px = (分布個(gè)數(shù)4-1)*間隙1px, 可以根據(jù)實(shí)際的分布個(gè)數(shù)和間隙區(qū)調(diào)整 min-width: calc((100% - 30px) / 4); max-width: calc((100% - 30px) / 4); &:nth-child(4n) { // 去除每行最后一個(gè)(第4n個(gè))的margin-right margin-right: 0; } } .yxt-search-button { margin: 0 0 10px 0; width: 100%; text-align: right; } } </style>
yxtTable.json
{ "retCode": "0", "retMsg": "success", "pageInfo": { "total": 300 }, "tasks": [ { "name": "張三", "code": "zhangSan", "status": 1, "icon": true, "phone": "17801010101", "selectable": 1 }, { "name": "李四", "code": "liSi", "status": 0, "icon": false, "phone": "17802020202", "selectable": 2 }, { "name": "王五", "code": "wangWu", "status": 2, "icon": true, "phone": "17803030303", "selectable": 0 }, { "name": "馬六", "code": "maLiu", "status": 1, "icon": false, "phone": "17804040404", "selectable": 2 } ] }
最后效果
感謝各位的閱讀,以上就是“elementUI el-table二次封裝的方法是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)elementUI el-table二次封裝的方法是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。