preface

In our daily development, we often use table components. Today, we will learn about its specific implementation. In fact, it is not the same. Ha ha, today also used a different theme, just found.

usage

Next, let’s look at the use of a very familiar table. In fact, in order to distinguish, I’m going to replace el with my; Then let’s implement the my-table and my-table-column components.

<my-table :data="tableData" style="width: 100%">
      <my-table-column prop="name" label="Name"></my-table-column>
      <my-table-column prop="date" label="Date"></my-table-column>
      <my-table-column prop="address" label="Address"></my-table-column>
      <my-table-column prop="opreation" label="Operation">
        <span slot-scope="scope">{{ scope.row.name }}</span>
      </my-table-column>
</my-table>
Copy the code

implementation

The source code for the Table component of Element-UI is too complex. Just to get a rough idea of how this works, let’s implement a demo version.

Train of thought

  • To render a table, mount the my-table-column component first and then the My-table component.
  • Each time you create a my-table-column component, you need to save all the header information and create a method to render each item of the table. If the header function slot content exists, the data is passed through the scope slot to the outer layer
  • Finally, in the my-table component, render the table

Code implementation

My – table – column components

<script>
import { store } from "./index";
export default {
  props: ["prop"."label"].created() {
    // Set the header information
    let item = {
      prop: this.prop,
      label: this.label,
    };
    item.renderCell = (data) = > {
      let children = null;
      // Does the table header have default slot content
      if (this.$scopedSlots.default) {
        // Use the scope slot to pass each row of data to the outside
        
      
        children = this.$scopedSlots.default(data);
      } else {
        // The value of the key corresponding to an item in the array according to the header property
        const { row, column } = data;
        children = row[column.prop];
      }
      return <div>{children}</div>;
    };
    store.columns.push(item);
  },
  render(h) {
    return h("div".this.$slots.default);
    // return <td>12</td>;}}; </script>Copy the code

Store instance

import Vue from 'vue'
// Very crudely use a vue instance to store the header information globally
const data = {
  columns: [],}const store = new Vue({
  data: data
})
export {
  store
}
Copy the code

My – table component

<script>
import { store } from "./index";
export default {
  props: {
    // Incoming data source
    data: {
      type: Array.default: () = > {
        return[]; }},},created() {
    store.columns.length = 0;
  },
  render() {
    // Use JSX syntax
    return (
      <div>{/* my-table-column default slot contents, default hidden do not display */}<div style={{ display: "none}} ">{this.$slots.default}</div>
        <table cellspacing="0" cellpadding="0">{/* Table header rendering, traversing the array of table header rendering */}<thead>
            <tr>
              {store.columns.map((item) => (
                <th>{item.label}</th>
              ))}
            </tr>
          </thead>{/* Table content rendering, 1. Preferred traversal of incoming data sources, 2. Render the contents of each TD according to the method stored in the table header. 3.<tbody>
            {this.data.map((item) => {
              return (
                <tr>{store.columns.map((column) => { const columnData = { ... column }; const data = { column: columnData, row: item, }; return<td>{column.renderCell(data)}</td>;
                  })}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>); }}; </script>Copy the code

The last

Find element-UI is a relatively powerful component library, use free time, understand a little bit of source content, or there will be harvest, finally, everyone to study ~