“This is the fifth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

A, effects,

This component is very simple to use and only requires the following configuration:

/** * Table column data (mandatory) * label Table column name * prop: Table data field name * width column width * align content alignment (center by default) * headerAlign (center by default) * columnType Whether slot is enabled * soltName Slot name (custom) */
    tableColumnOptions: [{label: "Account".prop: "id" },
    { label: "Name".prop: "name" },
    { label: "tag".prop: "type".columnType: true.soltName: "tag" },
    { label: "Special style".columnType: true.soltName: "link" },
    { label: "Operation".width: "300".columnType: true.soltName: "operation"},]Copy the code

Can display:

Second, technical points

1. Component value transfer

Pass data to child components through Prop

Prop is a set of custom attributes that you can register on components. When a value is passed to a prop attribute, it becomes a property of that component instance and is easy to use:

  • On the child component call tag of the parent component: Bind custom property names and property values
// partent.vue
<template>
  <div>// On the child component call tag of the parent component: bind the custom attribute name and attribute value<childTemp :title="partentTitle"></childTemp>
  </div>
</template>
<script>
import childTemp from "./child.vue"
export default {
    compontent:{childTemp},
    data(){
        return{
            partentTitle:"xxxxxxxx"}}}</script>


Copy the code
  • In the subcomponent: use props to receive the passed value and use the received data in the same way as in data
// child.vue
<template>
    <div>
        <h2>{{title}}</h2>
    </div> 
</template>
<script>
    export default {
        props: ['title'] // In the child component, use props to receive the title bound in the parent component
    }
</script>
Copy the code
Listen for child component events
  • Bind a function to the child’s click event via this.$emit(“Custom event name for a parent component“,parameter) Pass data
//child.vue
<template>
    <div>
        <button @click="childClick">button</button>
    </div> 
</template>
<script>
    export default {
        props: ['title'].data(){
            return{
                childData:"Data from child components"}},methods: {childClick(){
                this.$emit("fun".this.childData)
            }
        }
    }
</script>
Copy the code
  • In the parent component: Use v-bind (@ for short) on the call tag to bind the event name fun that was just defined in the child component, and give it a custom function. The arguments that were just passed in the child component via this.$emit are automatically injected into the arguments of the custom function
<template>
  <div>
      <childTemp @fun="getData"></childTemp>
  </div>
</template>

<script>
import childTemp from ".. /co/PropsChild.vue"
export default {
    components:{childTemp},
    data(){
        return{
            partentTitle:"xxxxxxxx"}},methods: {getData(e){//
            console.log(e); // Print out "data from child components"}}}</script>

Copy the code

2. Named slot

Named slots can appear in different places and have no limit on the number of times they can appear. As long as the name matches then the content will be inserted into the slot for the name.

Like v-on and v-bind, v-slot has an abbreviation that replaces everything before the argument (v-slot:) with the character #. For example, v-slot:header can be rewritten as #header:

  • The parent component

The
tag automatically takes the slot tag called header in the child component and replaces everything wrapped in the template tag with that slot tag

<template>
  <div>
    <childTemp>
        <template #header>If I write something here, it will automatically find a slot tag called header in the child component and replace it</template>
        <! </template> --> </template> -->
        <template #footer>If I write something here, it will automatically find a slot tag called footer in the child component and replace it</template>
    </childTemp>
  </div>
</template>

<script>
import childTemp from "./childTemp.vue";
export default {
  components: { childTemp }
};
</script>

</script>

Copy the code
  • The child components
<template>
  <div class="container">I'm not in the slot tag, so I'm still visible<header style="background:blue">
      <slot name="header">So what if I write it, as soon as somebody calls me, I'm replaced</slot>
    </header>
    <main style="background:red">
      <slot name="main">I'm still here if you don't call me</slot>
    </main>
    <footer style="background:pink">
      <slot name="footer"></slot>
    </footer>
  </div>
</template>
<script>
</script>
Copy the code

Prompt,

The V-slot directive was introduced since Vue 2.6.0 to provide a better API alternative that supports slot and slot-scope attributes. Slot and slot-scope attributes will still be supported in all subsequent 2.x releases, but have been officially deprecated and will not appear in Vue 3.

Get back to business and encapsulate components

The code for the encapsulated table component is as follows

BaseTable.vue

<template>
  <div id="Wrap">
    <! - form - >
    <el-table height="100px" @selection-change="selectionChange" class="table" :data="tableData" :border="hasBorder" :row-class-name="tableRowClassName">
     <el-table-column type="selection" width="50" v-if="selectionShow"> </el-table-column>
      <! - serial number -- -- >
      <el-table-column v-if="hasIndex" type="index" label="Serial number" header-align="center" align="center" width="80" > </el-table-column>
      <! -- -- -- > other
      <template v-for="item in tableColumnOptions">
        <! -- Slot column -->
        <el-table-column
          v-if="item.columnType"
          :key="item.label"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :header-align="item.headerAlign || 'center'"
          :align="item.align || 'center'"
        >
          <template slot-scope="{ row }">
            <slot :name="item.soltName" :data="row"></slot>
          </template>
        </el-table-column>
        <! -- Non-slot column -->
        <el-table-column
          v-else
          :key="item.label"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :header-align="item.headerAlign || 'center'"
          :align="item.align || 'center'"
        >
        </el-table-column>
      </template>
    </el-table>
    <! -- Pager -->
    <div class="pagination" v-if="paginationShow">
      <el-pagination
        :hide-on-single-page="isShowPagination"
        :page-sizes="[10, 20, 50, 100]." "
        :current-page="currentPage"
        :page-size="pageSize"
        :total="tableDataTotal"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      >
      </el-pagination>
    </div>
  </div>
</template>
<script type="text/ecmascript-6">
export default {
  name: "BaseTable".props: {
    // Table data
    tableData: {
      type: Array.default() {
        return[]; }},// Table entry
    tableColumnOptions: {
      type: Array.require: true.default() {
        return[]; }},// Total table data
    tableDataTotal: {
      type: Number.default() {
        return 0; }},// Whether there is an index
    hasIndex: {
      type: Boolean.default() {
        return true; }},// Whether to display a border
    hasBorder: {
      type: Boolean.default() {
        return false; }},// Whether to display the selection box
    selectionShow: {
      type: Boolean.default() {
        return true; }},// Whether to display the selected pager
    paginationShow: {
      type: Boolean.default() {
        return true; }},},data() {
    return {
      // The current page number of the table
      currentPage: 1.// Number of tables per page
      pageSize: 10}; },computed: {
    // Calculates whether the pager is displayed
    isShowPagination() {
      const isShow = this.tableDataTotal === 0;
      returnisShow; }},methods: {
    // The table changes color
    tableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2= =1) {
        return "color-row"; }},// Modify the current page
    handleCurrentChange(val) {
      const params = {
        currentPage: val,
        pageSize: this.pageSize,
      };
      this.$emit("tableUpdate", params);
    },
    // Change the number per page
    handleSizeChange(val) {
      const params = {
        currentPage: this.currentPage,
        pageSize: val,
      };
      this.$emit("tableUpdate", params);
    },
    // The selection box changes
    selectionChange(e){
      this.$emit('selectionChange',e)
    }
  },
};
</script>
<style  scoped>
#Wrap {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  background-color: #fff;
  display: flex;  
  flex-direction: column; } > > >.el-table{
  /* overflow-y:scroll! important; * /
}
#Wrap .pagination{
  margin-top: auto;
  margin-left: auto; } > > >.cell{
    text-align: center; } > > >.cell #link{
  font-family: MicrosoftYaHei;
  color: #445af7;
  cursor: pointer; } > > >.cell #delete {
  color: #ff5b5b;
  margin-left: 35px;
    cursor: pointer; } > > >.color-row{
  background-color: rgb(243.243.243); } > > >.el-table--border::after..el-table--group::after..el-table::before {
    content: ' ';
    position: absolute;
    background-color: transparent! important;
    z-index: 1;
}
</style>
Copy the code

Fifth, use

In the page to be used

<template>
  <div id="baseButton">
    <BaseTable
      :has-index="true"
      :has-border="false"
      :table-data="tableData"
      :table-data-total="tableData.length"
      :table-column-options="tableColumnOptions"
      @tableUpdate="tableUpdate"
      @selectionChange="selectionChange"
    >
      <! -- Type slot -->
      <template #tag="{ data }">
        <div class="tag">
          <el-tag type="success" v-if="data.type == 1">tag1</el-tag>
          <el-tag type="danger" v-if="data.type == 0">tag2</el-tag>
        </div>
      </template>
      <! -- Operation slot -->
      <template #operation="{ data }">
        <span @click="tableRowEdit(data)">The editor</span>
        <span @click="tableRowDelete(data)" id="delete">delete</span>
      </template>
      <! -- Link slot -->
      <template #link="{ data }">
        <span id="link" @click="check(data)">To view</span>
      </template>
    </BaseTable>
  </div>
</template>

<script>
import BaseTable from ".. /BaseTable.vue";
export default {
  components: {
    BaseTable,
  },
  methods: {
    selectionChange(e) {
      console.log("Select box changes:",e);
    },
    tableUpdate(e) {
      console.log("When the form changes",e);
    },
    tableRowEdit(e){
      console.log("Get the data for this row.",e); }},data() {
    return {
      // Table component -- simulates data
      tableData: [{id: 201791074073.name: "Zhang".type: 1 },
        { id: 201791074071.name: "Bill".type: 0 },
        { id: 201791074074.name: "A second".type: 0 },
        { id: 201791074074.name: "A second".type: 0 },
        { id: 201791074074.name: "A second".type: 1},]./** * Table column data (mandatory) * label Table column name * prop: * width Column item width * align content alignment (center by default) * headerAlign header alignment (center by default) * columnType Whether to enable slot * soltName Slot name */
      tableColumnOptions: [{label: "Account".prop: "id" },
        { label: "Name".prop: "name" },
        { label: "tag".prop: "type".columnType: true.soltName: "tag" },
        { label: "Special style".columnType: true.soltName: "link" },
        { label: "Operation".width: "300".columnType: true.soltName: "operation"},]}; }};</script>
Copy the code

ColumnType will slot open and soltName slot name. ColumnType will slot open and soltName. Use named slots in the baseTable tag to write your particular style.

In this way, we call this component in different pages, not only ensure the different page table style is consistent, also ensure that the difference of the different pages, is the biggest benefit of using this component, form the style of the uniform set within the encapsulated form component, a change, other parts change, can rapid global change style.

over