PrefaceAs the business develops and the functions increase, we find that many pages have similar functions. Here are a few common examples: drop-down menus with multiple selections, dialog boxes with input, date pickers, etc. So we will try to extract these common functions into common components so that they can be used in different pages or businesses. Why do we need to encapsulate the table component?The tables in the background management system are used frequently, which reduces the business code about the tables and facilitates unified modification and maintenance in the later stage. For example, when displaying table contents, ellipsis is used to display the contents outside the cell. For most backend management systems, the display of data tables is similar. Since I don’t want to write duplicate code, I choose to encapsulate the general table component to free my hands. If your table has a column that is not a simple DOM element, such as a switch button, you can pass in a render function to achieve your goal. Step 1: Define common components<!-- pro-table.vue --> <template> <div> <el-table :data="tableData" style="width: 100%" :stripe="tableTitle.stripe" :border="tableTitle.border" :fit="tableTitle.fit" :highlight-current-row="tableTitle.highlightCurrentRow" @selection-change="handleSelectionChange"> <!--First column of the table--> <el-table-column :type="firstTableCol.type" :width="firstTableCol.width" v-if="firstTableCol.select" > </el-table-column> <!--Other columns in the table--> <el-table-column v-for="(value,index) in tableCol" :key="index" :prop="value.prop" :label="value.label" :width="value.width || 180"> <template slot-scope="scope"> <template v-if="!value.render"> <template v-if="value.formatter"> {{ value.formatter(scope.row, value) }} </template> <template v-else-if="value.getImgurl"> <el-image :src="value.getImgurl(scope.row, value)" style="width: 70px; height: 70px" :preview-src-list="value.previewSrcList ? value.previewSrcList(scope.row, value) : value.getImgurl(scope.row, value).split(',')"/> </template> <template v-else> {{ scope.row[value.prop] }} </template> </template> <!--Extended DOM--> <template v-else> <Table :key="`cus${index}`" :render="value.render" :param="scope.row"></Table> </template> </template> </el-table-column> <!--Basic operations--> <el-table-column label="operation"> <template slot-scope="scope"> <el-button type="text" v-for="(value,index) in operator" @click="value.click(scope.row, value)" :key="index"> {{ value.text }} </el-button> </template> </el-table-column> </el-table> <!--Pagination plugin--> <el-pagination v-show="total>0" :total="total" :page-size.sync="pageSize" :current-page.sync="currentPage" :page-sizes="[10, 20, 30, 50]" layout="total, sizes, prev, pager, next, jumper" @current-change="handleCurrentChange" @size-change="handleSizeChange" v-bind="$attrs"> </el-pagination> </div> </template> <script> // render function import Table from './table' export default { components: {Table}, props: { tableTitle: { type: Object, default: { stripe: false, border: false, fit: true, highlightCurrentRow: false } }, firstTableCol: { type: Object, default: { select: false, width: 55, type: 'selection' } }, tableCol: { type: Array, default: [] }, tableData: { type: Array, default: [] }, operator: type: Array, default: [] }, total: type: Number, default: 0 }, page: { type: Number, default: 1 }, limit: { type: Number, default: 10 }, autoScroll: { type: Boolean, default: true } }, computed: { currentPage: { get () { return this.page }, set (val) { this.$emit('update:page', val) } }, pageSize: { get () { return this.limit }, set (val) { this.$emit('update:limit', val) } } }, data () { return { } }, methods: { // Listen to the table selection box handleSelectionChange (selection) { //Call the handleSelectionChange method corresponding to the parent component this.$emit('handleSelectionChange', selection) }, // How many records per page should be monitored (limit) handleSizeChange (limit) { this.$emit('pagination', {page: this.currentPage, limit: limit}) if (this.autoScroll) { scrollTo(0, 800) } }, // Monitor the current page (page) handleCurrentChange (page) { this.$emit('pagination', {page: page, limit: this.pageSize}) if (this.autoScroll) { scrollTo(0, 800) } } } } </script> <style scoped> </style> Step 2: Render communication between parent component and child componentIn order to make the parent component render function take effect in the child component, we need to define a render function and reference it in the child component. // table.js export default { props: { render: { type: Function }, param: { type: Object } }, render(h) { return this.render(h, this.param) } } Step 3: Using Components<template> <div> <!-- @Custom event="parent component method", in the child component, this.$emit('custom event name') triggers the parent component event. ref="proTable", marked on the subcomponent, pointing to the subcomponent instance --> <proTable ref="proTable" :tableTitle="tableTitle" :tableCol="tableCol" :tableData="tableData" :operator="operator" :firstTableCol="firstTableCol" @handleSelectionChange="handleSelectionChange" :total="total" :page.sync="queryParams.page" :limit.sync="queryParams.limit" @pagination="getList"/> </div> </template> <script> import proTable from './pro-table' export default { components: proTable }, data() { return { queryParams: { page: 1, limit: 10, }, type: 'success', total: 50, // Setting table attributes in element-ui tableTitle: { 'stripe': true, "highlightCurrentRow": true }, // Set the table column tableCol: [ { prop:'date',label:'date'}, { prop:'name',label:'Name'}, { prop:'address',label:'Address',width: 300}, { prop:'src',label:'Picture', getImgurl: (row, col, cellValue) => { return this.getImgurl(row)}, previewSrcList: (row, col, cellValue) => {return this.listImgUrl(row)}}, { prop:'sex', label:'Gender', formatter: (row, col, cellValue) => {return this.sexFormatter(row)}}, { prop:'src',label:'Picture', getImgurl: (row, col, cellValue) => { return this.getImgurl(row)}}, { prop:'text',label:'function', render: (h, params) => {return this.render(h, params)}} ], // Basic table operations operator: [ {'text':'Details', click: (row, col, cellValue) => {return this.getInfo(row)}}, {'text':'Delete', click: (row, col, cellValue) => {return this.delInfo(row)}}, {'text':'Edit', click: (row, col, cellValue) => {return this.editInfo(row)}}, ], // Simulation data tableData: [ { date: '2016-05-02', name: 'Wang Xiaohu', address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai', sex: 0, img:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic2.zhimg.com%2F50%2Fv2-193cbb243dc14d3a016caaa54ba02837_hd.jpg&refer=http%3A%2F%2Fpic2.zhimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628435704&t=deb5584cb9ff53fe6977f14a5e0755bb' }, { date: '2016-05-04', name: 'Wang Xiaohu', address: 'No. 1517, Jinshajiang Road, Putuo District, Shanghai', sex: 1, img:'https://pic1.zhimg.com/80/v2-894ab624807fd4cfa33dd4e42cc90ac8_720w.jpg?source=1940ef5c' }, { date: '2016-05-01', name: 'Wang Xiaohu', address: 'No. 1519, Jinshajiang Road, Putuo District, Shanghai', sex: 0, img:'xx.jpg' }, { date: '2016-05-03', name: 'Wang Xiaohu', address: 'No. 1516, Jinshajiang Road, Putuo District, Shanghai', sex: 1, img:'xx.jpg' }], firstTableCol: { 'select': true, 'type': 'selection' } } }, methods: { getInfo(val) { // Trigger the parent method console.log("Get details",val) }, delInfo(val) { // Trigger the parent method console.log("delete information",val) }, editInfo(val) { // Trigger parent method console.log("Edit information",val) }, getImgurl(val) { console.log(val.img) return val.img }, sexFormatter(val) { return val.sex === 0 ? 'male' : 'female' }, handleSelectionChange(val) { console.log("listen selection box",val) }, getList(queryParams) { console.log("parent method",queryParams) }, listImgUrl() { let array = []; array.push("https://pic1.zhimg.com/80/v2-894ab624807fd4cfa33dd4e42cc90ac8_720w.jpg?source=1940ef5c"); array.push("https://cdn.pixabay.com/photo/2021/07/01/21/20/girl-6380331_960_720.jpg"); return array; }, render(h, params) { return h('span', null, 'I am a render component') } } } </script> SummarizeIn the page that references the component, we can add methods to each table column, and we can also add custom methods to edit, delete, and details to fully achieve customization. You can also customize the render function. The effect diagram is as follows: This is the end of this article about Vue encapsulation of universal table components. For more relevant Vue encapsulation of universal table components, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: MySQL trigger definition and usage simple example
>>: How to build Git service based on http protocol on VMware+centOS 8
Step 1: Get the MySQL YUM source Go to the MySQL ...
Copy code The code is as follows: <!DOCTYPE ht...
1. DOCTYPE is indispensable. The browser determin...
Source of the problem: If the slave server is the...
Today I found that a program inserted an incorrec...
The specific code for implementing the retractabl...
Several problems were discovered during the use o...
Table of contents Overview Type Assertions in syn...
1. If MySQL is not started successfully, check th...
background nginx-kafka-module is a plug-in for ng...
I have been in contact with PHP for so long, but ...
Main library configuration 1. Configure mysql vim...
Today I will talk about a CSS special effect of h...
The following content introduces the process and ...
This article shares the MySQL installation tutori...