This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging

Recently I opened a new project to briefly describe my table encapsulation.

Problem analysis

Why encapsulate

First of all, why encapsulate table? Is it because of technology? No, it is because of laziness.

What are the contents of the package

There are two main components, a table component and a paging component

Once you have that figured out, you can start wrapping components.

Encapsulating the Table component

Validate data format

To determine the data format, we need to look at the el-table component

<el-table :data="tableData" style="width: 100%">
   <el-table-column prop="date" label="Date" width="180" />
   <el-table-column fixed="right" label="Operation" width="100">
      <template slot-scope="scope">
        <el-button @click="handleClick(scope.row)" type="text" size="small">To view</el-button>
        <el-button type="text" size="small">The editor</el-button>
     </template>
   </el-table-column>
</el-table>
Copy the code

Now let’s think about data types like Lebel, prop, widht button types, events, and so on,

let paramsType = {
  data: Array./ / data
  loading: Boolean.selectionShow: Boolean.columns:Array= [{label: String.prop: String.filter: Function.isSlot: Boolean.width: Number.tempalte: Function.btns: Array= [{name: String.btnType: String.clickType: String.routerType: String.url: String.query: Function.btnClick: Function}]}]}Copy the code

With the number data document defined, we can begin to encapsulate the component

Packaging components

Encapsulating global Components

The reason for wrapping global components is to save trouble, all of it, all of it. Create a components file under SRC and write our components in it. Each component is recommended to have a separate folder for easy maintenance.

Create your own table.vue component. I’ll call it FrTable.

The global use imports the FrTable file into the index.js file under components, where all components are traversed and exported

The code is as follows:

import TrTable from './FrTable/index'

const components = [TrTable]

const install = (Vue) = > {
  components.map(component= > {
    Vue.component(component.name, component)
  })
}

if (typeofWindow ! = ='undefined' && window.Vue) {
  install(Window.Vue)
}

export default {
  install
}
Copy the code

Then export to main.js and use the component with vue.use (), as shown below

import globalComponents from '@/components/index'
Vue.use(globalComponents)
Copy the code

Use in pages

<fr-table />
Copy the code

Table Component Encapsulation

Questions to consider

How many cases are there in the table,

  1. Normal data type display
  2. Unique way to show
  3. There are operation buttons

For the first type, we don’t really need to do much, we just need to render through the for loop.

The second one is actually fine, we can customize it through slot

Third, the operation of buttons. There are many types of buttons

Type of button
  1. For normal use of the button, click the function
  2. The button acts as a jump
  3. The button opens a new page
  4. Buttons act as custom events

Code writing

Now that we’ve analyzed all the problems with the table, we just need to type in the code.

Case one
<el-table :data="data" border :loading="loading"> <! - check -- - ><el-table-column v-if="selectionShow" type="selection" width="50" align="center" :reserve-selection="true" />
     <template v-for="(item, index) in columns">
        <el-table-column :key="index" v-bind="item">
            <! -- Custom table header -->
          <template v-if="item.customHeader" slot="header">
              <slot :name="item.headerProp" />
          </template>
          <template slot-scope="scope">
               <span v-html="handleFilter(item, scope.row, item.prop)" />
          </template>
        </el-table-column>
     </template>
 </el-table>
Copy the code

So here we can see the handleFilter method which handles the data,

Data types are classified into normal data types, data types to be converted, and data types to be converted by templates. The codes are as follows

handleFilter(item, val, prop) {
  let value = val[prop]
  if (item.templet) value = item.templet(val)
  return item.filter ? this.$options.filters[item.filter](val[prop]) : value
},
Copy the code

The first case is simple, with simple data rendering and custom header rendering, and the overall top is multiple selections + normal forms

Case two

Custom lists

<template slot-scope="scope"> <! -- Custom content --><slot
      v-if="item.isSlot"
      :name="item.prop"
      :row="scope.row"/
   >
</template>
Copy the code

For a custom category, we just need isSlot set to true, name to Prop, and Row to data

The third kind of

The third button is divided into four cases

<template v-if="item.btns">
   <el-button
     v-for="(btn, i) in item.btns"
     :key="i"
    class="mr_10"
    :size="btn.mini ? btn.mini: 'small'"
    :type="btn.type ? btn.type: 'primary'"
    @click="btnClickfunc(btn, scope.row)"
  >
     {{ btn.name }}
  </el-button>
</template>
Copy the code

The button is still looped, mainly event analysis, through the btnClickfunc event operation.

btnClickfunc(column, row) {
      const path = {
        [column.routerType]: column.url,
        query: column.query ? column.query(row) : ' '
      }
      if (column.clickType === 'router') {
        this.$router.push(path)
      } else if (column.clickType === 'router_blank') {
        const routeData = this.$router.resolve(path)
        window.open(routeData.href, '_blank')}else if (column.clickType === 'btnClick') {
        column.btnClick(row)
      } else {
        this.$emit('btnClickFunc', { column: column, row: row })
      }
},
Copy the code

We do different things for different types.

Props specifies the value of the props parameter

The current parameters are the same as the parameters we defined, so the code is as follows

  / / data
    data: {
      type: Array.required: true
    },
    // Header parameters
    columns: {
      type: Array.required: true
    },
    loading: {
      type: Boolean.default: false
    },
    // Multi-checkbox selection
    selectionShow: {
      type: Boolean.default: false
    },
Copy the code

From there, all that remains is how the components are used

Use of components
<fr-table
      ref="mt"
      :loading="loading"
      :data="list"
      :columns="columns"
    >
</fr-table>
Copy the code

Basically, if you need to use multiple choices, define your own method, same with sorting.

Paging Component Encapsulation

Refer to the Element paging component

<el-pagination
  style="margin-top:40px;"
  background
  layout="prev, pager, next"
  :page-size="pageLimit"
   :total="total"
   :current-page="currentPage"
   @current-change="handleCurrentChange"
/>
handleCurrentChange(val) {
   console.log(val)
}
Copy the code

Data definition

The definition is as follows:

total: Number.pageLimit: Number.currentPage: Number.Copy the code

encapsulation

<el-pagination
  style="margin-top:40px;"
  background
  layout="prev, pager, next"
  :page-size="pageLimit"
  :total="total"
  :current-page="currentPage"
  @current-change="handleCurrentChange"
/>

handleCurrentChange(val) {
   this.$emit('currentChange', val)
}
Copy the code

If it looks simple, it is.

We then add the paging events and parameters to the component, and our entire table component encapsulation is complete.

The above is all knowledge points, there is insufficient to point out, please also give advice!!

Related articles

Lerna, development and release processJuejin. Cn/post / 699221…

Promise to reviewJuejin. Cn/post / 699183…

Let, const reviewJuejin. Cn/post / 699147…

Beginner koA building projectJuejin. Cn/post / 698756…

Regular Expression SummaryJuejin. Cn/post / 698615…

Flex Layout SummaryJuejin. Cn/post / 698497…

Basic Usage of mongodbJuejin. Cn/post / 698364…

Vue3 Setup management background – project setupJuejin. Cn/post / 696802…

Factory patterns, constructor patterns, and prototype patternsJuejin. Cn/post / 695794…