提示:請先看第二步中的組件說明,和組件封裝中其他擴展的api,的注釋都在html中對應的代碼結構都有主要依靠JSON數據動態執行和回調
特點:通過JSON數據動態渲染列表標題和數據列表,JSON數據驅動事件監聽和回調以及數據過濾,和滿足更多自定義需求組合
效果圖:
下面這種模式可以點擊圖片,可以是一張圖片,也可以數組中多個圖片,點擊圖片可以預覽切換
1.頁面調用(記得進行引入組件后在調用)
<table-List :tableData="tableData" :tableLabel="tableLabel" :choice="true" pagingPosition="center" :paging="true" :operation="operation" :total="total" headerAlign='center' @handleNumberChange="handleNumberChange" @sortChange="sortChange" @select="select" :headButton="true" @handleCurrentPage="handleCurrentPage"> <template v-slot:second> <el-button type="primary" size="mini" ><i class="el-icon-download"></i> 導出</el-button> </template> </table-List>
import tableList from '@/components/tableList' components:{
tableList,
}, data(){ return{ tableData: [],//數據源 tableLabel:[ { prop: 'nickName', label: '用戶昵稱', align: 'center', }, { prop: 'friendCount', label: '好友數量', align: 'center', }, ], operation:{ width: '220', Button:[ { label: '查看', size: "mini", authority: false, callback(k) { console.log(k) } } ] }, total:10, } } , methods:{ handleNumberChange(val){},// 每一頁展示多少條切換 handleCurrentPage(val){},//切換分頁 sortChange(column){},// 排序 select(valArr){},//列表復選框 }
2.封裝組件核心代碼
<template> <div style="height: 100%;"> <!-- 這里插槽主要是自定義頭部標簽操作按鈕 --> <div style="padding: 5px 0;" v-if="headButton"> <slot name="second"></slot> </div> <el-table :data="tableData" :row-key="rowKey" border @sort-change='sortChange' @select="select" :highlight-current-row="true" @select-all="select" :header-cell-style="{'text-align':headerAlign,'background':'#eef1f6'}" @current-change="handleCurrentChange" :max-height="fixedHeight>0?fixedHeight:tableHeight-difference" :ref="Math.random()"> <!-- 復選框 --> <el-table-column type="selection" v-if="choice" width="50" :align="headerAlign" :key="Math.random()"> </el-table-column> <!-- 序號 --> <el-table-column label="序號" v-if="serialNumber" width="50" type="index" :align="headerAlign" :key="Math.random()"> <template slot-scope="scope"> {{searchData.limit * (searchData.page - 1) + (scope.$index + 1)}} </template> </el-table-column> <!-- 動態表頭 --> <!-- { prop:'title',// 列表渲染的字段key label:'菜單名稱',// 字段中文名稱 align:''// 列表內容文字的位置 sort:true, // 是否排序 form:'string', (可選:string/img/Button/filter/select) key:{label: "label",value: "value"} // 這個配置是下拉框的form = select filter(row){},// 對數據進行過濾 並返回內容 和vue 過濾器一樣的功能 configure:{ // 配置按鈕的參數對象 type:''// 參考el-button 官網參數 size:''// 參考el-button 官網參數 }, callback(row){} //點擊按鈕的回調函數 } --> <div v-for="(item, index) in tableLabel" :key="index"> <!-- 普通數據展示/或者字符串文本展示 --> <el-table-column v-if="!item.form || item.form ==='string'" :prop="item.prop" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index" show-overflow-tooltip> </el-table-column> <!-- 數據過濾:根據filter函數自定義規則進行數據返回 --> <el-table-column v-else-if="item.form === 'filter'" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index" show-overflow-tooltip> <template slot-scope="scope"> {{item.filter(scope.row)}} </template> </el-table-column> <!-- 圖片展示 --> <el-table-column v-else-if="item.form === 'img'" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index"> <template slot-scope="scope"> <!-- 如果是字符串就是一個圖片 --> <div v-if="typeof scope.row[item.prop] === 'string'"> <el-image style="width: 22px; height: 22px" :src="scope.row[item.prop]?scope.row[item.prop]:defaultImg" :preview-src-list="[scope.row[item.prop]?scope.row[item.prop]:defaultImg]"> </el-image> </div> <!-- 不是字符串就統一數組來處理 --> <div v-else-if="scope.row[item.prop]!==null&& scope.row[item.prop].length>0"> <span v-for="(item1,index1) in scope.row[item.prop]" :key="index1"> <el-image style="width: 22px; height: 22px;margin-right: 20px;" :src="scope.row[item.prop][index1]" :preview-src-list="scope.row[item.prop]" :z-index='2100'> </el-image> </span> </div> </template> </el-table-column> <!-- 按鈕展示 --> <el-table-column v-else-if="item.form === 'Button'" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index"> <template slot-scope="scope"> <el-button @click="item.callback&&item.callback(scope.row)" :type="item.configure&&item.configure.type?item.configure.type:''" :size="item.configure&&item.configure.size?item.configure.size:''"> {{item.configure.text||'缺少按鈕文字'}}</el-button> </template> </el-table-column> <!-- 多個復選框 --> <el-table-column v-else-if="item.form === 'checkbox'" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index"> <template slot-scope="scope"> <span style="margin-left: 5px;" v-for="(v,i) in scope.row.authority" :key="i"> <el-checkbox :label="v.name" name="type" v-model="v.open"></el-checkbox> </span> <span v-if="scope.row.authority&&scope.row.authority.length<1">暫無</span> </template> </el-table-column> <!-- 單選框 --> <!-- 表頭配置tableLabel --> <!-- { prop: 'timeType',最終下拉框每次選中的值都綁定到 這個定義的字段上 label: '時間單位', align: 'center', form: "radio", key: { label: "label", value: "value" }, width: 250, }, --> <!-- 列表循環數據 每一項必須要有 radioList屬性為數組 --> <el-table-column v-else-if="item.form === 'radio'" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index"> <template slot-scope="scope" > <div v-if="scope.row.radioList && scope.row.radioList.length"> <el-radio-group v-model="scope.row[item.prop]"> <el-radio v-for="items in scope.row.radioList" :key="items[item.key.value]" :label="items[item.key.value]" >{{items[item.key.label]}}</el-radio> </el-radio-group> </div> <div v-else> <span style="color: #e6a23c;">缺少radioList屬性數組!</span> </div> </template> </el-table-column> <!-- 下拉框 --> <!-- 表頭配置tableLabel --> <!-- { prop:'xxx' 最終下拉框每次選中的值都綁定到 這個定義的字段上 form:'select', key:{label: "label",value: "value"} } --> <!-- 列表循環數據 每一項必須要有 options屬性為數組 --> <el-table-column v-else-if="item.form === 'select'" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index"> <template slot-scope="scope"> <el-select v-model="scope.row[item.prop]" placeholder="請選擇" size="mini"> <el-option v-for="items in scope.row.options" :key="items[item.key.value]" :label="items[item.key.label]" :value="items[item.key.value]"> </el-option> </el-select> </template> </el-table-column> <!-- 輸入框 --> <el-table-column v-else-if="item.form === 'input'" :width="item.width" :label="item.label" :sortable="item.sort" :align="item.align?item.align:'left'" :key="index"> <template slot-scope="scope"> <el-input placeholder="請輸入內容" v-model="scope.row[item.prop]"size="mini" > </el-input> </template> </el-table-column> </div> <el-table-column label="操作" :width="operation.width" v-if="JSON.stringify(operation)!== '{}'"> <template slot-scope="scope"> <!-- 操作按鈕 --> <!-- { label:'刪除', type:'danger',// 按鈕類型 參考el-button 官網參數 size:"mini", // 按鈕大小 參考el-button 官網參數 plain:true, // 是否朴素按鈕 callback(row){}, // 點擊按鈕回調函數 disabled(row){ return true/false} //是否禁用 可以條件判斷 讓函數返回布爾值 authority:true// 如果涉及到權限按鈕控制的 就添加這個屬性(false普通按鈕/true權限按鈕) authorityEvent(row){return true/false} } --> <!-- 動態操作按鈕 --> <div class="flex center"> <div class="flex center" v-for="(item,index) in operation.Button" :key="index"> <el-button style="margin: 0 5px;" v-if="!item.authority" @click="item.callback(Object.assign({},scope.row))" :type="item.type?item.type:''" :size="item.size?item.size:''" :disabled="item.disabled&&item.disabled(scope.row)" :plain="plain">{{item.label}}</el-button> <el-button style="margin: 0 5px;" v-else-if="item.authority && item.authorityEvent&& item.authorityEvent(item.label)" @click="item.callback(Object.assign({},scope.row))" :type="item.type?item.type:''" :size="item.size?item.size:''" :disabled="item.disabled&&item.disabled(scope.row)" :plain="plain">{{item.label}}</el-button> </div> </div> </template> </el-table-column> </el-table> <!-- 分頁 --> <div style="padding: 10px;" v-if="paging" :style="{'text-align':pagingPosition}"> <el-pagination @size-change="handleNumberChange" @current-change="handleCurrentPage" :current-page="searchData.page" :page-sizes="[10,15, 20, 30, 40,50]" :page-size="searchData.limit" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination> </div> </div> </template> <!-- /** * 組件說明 * 屬性: * 參數 說明 類型 默認值 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * tableData 列表 的數據源 Array [] * treeProps 支持樹類型的數據的列表顯示 Object {children: 'children'} * rowKey 樹類型的數據 列表必須要指定 String '_id' * serialNumber 是否需要序號 Boolean true * headerAlign 表頭對齊方式/復選框/序號 String 'left'/'center'/'right' * tableLabel 動態表頭渲染數組 Array [] * choice 是否開啟多選復選框 Boolean false * operation 操作列表按鈕 Object {} * total 分頁總頁數 number 0 * paging 是否開啟分頁 Boolean false * pagingPosition 分頁底部的位置 String 'left'/'center'/'right' * fixedHeight 固定table列表高度 number 0 * pagingPage 分頁參數 Object {pageSize: 20,page: 1} * headButton 列表頭部按鈕是否顯示 Boolean false * 回調事件: * select 獲取復選框選中對象 返回數組 * sortChange 獲取當前點擊表頭指定排序結果 * handleCurrentPage 每次切換頁數觸發並且回調頁數 * handleNumberChange 每次切換展示的條數觸發並且回調 */ --> <script> const defaultImg = require('../../assets/image/user.png') export default { components: { }, props: { plain: { type: Boolean, default: true }, headButton: { type: Boolean, default: false }, tableData: { // 數據 type: Array, default: () => ([]) }, treeProps: { // 支持樹類型的數據的顯示 type: Object, default: () => ({ children: 'children' }) }, rowKey: { //樹類型的數據 列表必須要指定row-key id type: String, default: '_id' }, serialNumber: { // 是否需要序號 type: Boolean, default: true }, headerAlign: { type: String, default: 'left' }, tableLabel: { type: Array, default: () => ([]) }, choice: { type: Boolean, default: false }, operation: { type: Object, default: () => ({}) }, total: { type: Number, default: 0 }, paging: { type: Boolean, default: false }, pagingPosition: { type: String, default: 'left' }, fixedHeight: { type: Number, default: 0 }, pagingPage: { type: Object, default: () => ({ limit: 15, page: 1 }) }, // 設置偏移高度(到達每個頁面不同內容高度,都可以讓列表高度填充滿整個可視區) difference:{ type: Number, default: 0 } }, data() { return { defaultImg: defaultImg, tableHeight: document.documentElement.clientHeight-(70+80), // 表格自適應高度 默認撐滿 // 分頁固定參數 searchData: { limit: this.pagingPage.limit, page: this.pagingPage.page } } }, watch: { }, created() { }, methods: { // 重置分頁參數 pagingReset(limit,page){ if(!limit && !page){ this.searchData.limit = 15; this.searchData.page = 1 } else if(limit){ this.searchData.limit = limit; } else { this.searchData.page = page } }, test(){ console.log('添加事件') }, // 切換頁數 handleCurrentPage(val) { this.searchData.page = val this.$emit('handleCurrentPage', val) }, // 每頁N展示條 handleNumberChange(val) { this.searchData.limit = val this.$emit('handleNumberChange', val) }, // 復選框勾選 select(row) { this.$emit('select', row) }, // 排序 sortChange(column, prop, order) { this.$emit('sortChange', column) }, // 點擊列表 獲取數據 handleCurrentChange(row) { // console.log(row) } } } </script> <style scoped> /* 默認el-table 行高過於高,這里設置減少padding之間的間距 */ /deep/ th { padding: 9px 0; } /deep/ .el-table td { padding: 9px 0; } </style>
我是馬丁的車夫,歡迎轉發收藏!