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
This article introduces the characteristics of CS...
Nginx can use its reverse proxy function to imple...
This article example shares the specific code of ...
1. Start the Docker container Start a new Docker ...
Table of contents Overview 1. Clearly understand ...
Preface In this article, we'll explore the ev...
The installation information on the Internet is u...
Table of contents Overview Example Why is it need...
I won't say much nonsense, let's just loo...
Using the image service deployed by docker stack,...
<br />When inserting music into a web page, ...
When using docker, you may find that the file can...
The filter attribute defines the visual effect of...
Current demand: There are two tables, group and f...
In an unordered list ul>li, the symbol of an u...