vue3新拟态组件库开发流程之table组件源码分析

Vue3新拟态组件库开发流程之table组件源码分析攻略

1. 前言

Vue3作为一款优秀的前端框架,不断地为前端开发者带来更加方便和高效的开发模式。其中,拟态风格越来越受到大家的关注,为此,我们今天就来学习一下Vue3新拟态组件库开发流程中的table组件源码分析。

2. 源码分析

2.1. 源文件结构

table组件的源码位于/src/components/table目录下,相关文件和目录如下:

- table/
  - index.js
  - table.vue
  - table-cell.vue
  - table-header.vue
  - table-row.vue

源文件结构非常清晰,其中index.js是对外的入口文件,table.vue是table组件的主体代码。

2.2. 主体代码分析

首先,我们先看一下table.vue的代码。

<template>
  <table>
    <thead>
      <tr>
        <TableHeader
          v-for="(column, key) in columns"
          :key="key"
          :column="column"
          @sortChange="handleSortChange"
        />
      </tr>
    </thead>
    <tbody>
      <TableRow
        v-for="(row, rowIndex) in rows"
        :key="rowIndex"
        :row="row"
        :columns="columns"
      />
    </tbody>
  </table>
</template>

<script>
import TableHeader from './table-header.vue'
import TableRow from './table-row.vue'

export default {
  name: 'VTable',
  components: {
    TableHeader,
    TableRow
  },
  props: {
    columns: {
      type: Array
    },
    rows: {
      type: Array
    },
    sortColumn: {
      type: String,
      default: ''
    },
    sortOrder: {
      type: String,
      default: 'ascending'
    }
  },
  methods: {
    handleSortChange(column) {
      this.$emit('sort-change', column)
    }
  }
}
</script>

可以看到,table.vue主体代码非常简单,只包含一个<table>标签,其中含有两个子组件TableHeaderTableRow,还有几个props和一个监听事件。我们可以针对这几个部分做一个具体分析。

2.2.1. TableHeader部分

接下来我们看一下TableHeader组件的代码,它负责将传入的列信息展示在表格上部。TableHeader组件的代码如下:

<template>
  <th>
    <slot>{{ column.label }}</slot>
    <span v-if="column.sortable" class="sort-icon" :class="{ active: isSorted(column) }">
      <svg viewBox="0 0 24 24">
        <path
          d="M7.41 8.59L6 7.17V21a1 1 0 0 0 2 0V7.17l-1.41 1.42A1 1 0 0 0 6 9a1 1 0 0 0 .71.29 1 1 0 0 0 .7-.29l2.58-2.59a1 1 0 0 0 0-1.41 1 1 0 0 0-1.41 0z"
        />
      </svg>
    </span>
  </th>
</template>

<script>
export default {
  name: 'TableHeader',
  props: {
    column: {
      type: Object
    }
  },
  methods: {
    isSorted(column) {
      return column.prop === this.sortColumn
    },
    handleClick() {
      this.$emit('sortChange', this.column.prop)
    }
  }
}
</script>

主要由一个<th>标签组成,标签内部包含列名称column.label和排序图标。排序图标的显示受到列是否可排序以及当前列是否是排序列的影响。

2.2.2. TableRow部分

接下来我们看一下TableRow组件的代码,它负责将传入的行信息展示在表格上。TableRow组件的代码如下:

<template>
  <tr>
    <TableColumn
      v-for="(column, key) in columns"
      :key="key"
      :column="column"
      :row="row"
    />
  </tr>
</template>

<script>
import TableColumn from './table-column.vue'

export default {
  name: 'TableRow',
  components: {
    TableColumn
  },
  props: {
    columns: {
      type: Array
    },
    row: {
      type: Object
    }
  }
}
</script>

TableRow包含多个<TableColumn>组件,对于每一列信息,它都会将它传入到TableColumn组件内部去渲染,这里使用了v-for指令来遍历所有列信息并渲染。TableColumn组件是一个公共组件,我们将在下一个小节进行讲解。

2.2.3. TableColumn部分

最后我们看一下TableColumn组件的代码,它负责将传入的数据信息展示在表格上。TableColumn组件的代码如下:

<template>
  <td>
    <slot>{{ row[column.prop] }}</slot>
  </td>
</template>

<script>
export default {
  name: 'TableColumn',
  props: {
    column: {
      type: Object
    },
    row: {
      type: Object
    }
  }
}
</script>

我们看到,TableColumn组件仅仅只包含一个<td>标签,同时它也使用了插槽来动态获取每一行的指定列中的值并进行渲染。这里我们对组件的重利用达到了最大的优化。

3. 示例说明

我们该如何使用这个table组件呢?下面我们来举两个简单的示例说明。

3.1. 基本用法

<template>
  <div>
    <VTable
      :columns="columns"
      :rows="rows"
      @sort-change="sortChangeHandler"
      :sortColumn="sortColumn"
      :sortOrder="sortOrder"
    />
  </div>
</template>

<script>
import VTable from '@/components/table/index.js'

export default {
  name: 'example',
  components: {
    VTable
  },
  data() {
    return {
      columns: [
        { label: '姓名', prop: 'name', sortable: true },
        { label: '年龄', prop: 'age', sortable: true },
        { label: '性别', prop: 'gender' }
      ],
      rows: [
        { name: '小明', age: 18, gender: 1 },
        { name: '小红', age: 16, gender: 0 },
        { name: '小李', age: 20, gender: 1 },
        { name: '小白', age: 18, gender: 0 },
        { name: '小黄', age: 19, gender: 1 }
      ],
      sortColumn: '',
      sortOrder: 'ascending'
    }
  },
  methods: {
    sortChangeHandler(column) {
      if (column === this.sortColumn) {
        this.sortOrder = this.sortOrder === 'ascending' ? 'descending' : 'ascending'
      } else {
        this.sortColumn = column
        this.sortOrder = 'ascending'
      }
      this.sortRows()
    },
    sortRows() {
      this.rows.sort((row1, row2) => {
        let ascending = this.sortOrder === 'ascending' ? 1 : -1
        let descending = -ascending
        if (row1[this.sortColumn] > row2[this.sortColumn]) {
          return ascending
        } else if (row1[this.sortColumn] < row2[this.sortColumn]) {
          return descending
        } else {
          return 0
        }
      })
    }
  }
}
</script>

以上代码实现了一个简单的表格展示功能,其中columnsrows是table组件的props,分别对应表格的列信息和行信息。如果某一列可以排序,对应的column对象中的sortable值为true,并且用户可以点击表头中的排序图标进行升序或降序排列。sortColumnsortOrder分别表示当前排序的列和顺序。

3.2. 带分页功能

<template>
  <div>
    <div class="table-pagination">
      <el-pagination
        v-model="currentPage"
        :total="rows.length"
        :page-size="pageSize"
        :current-page.sync="currentPage"
        :prev-text="'上一页'"
        :next-text="'下一页'"
        :layout="'prev, pager, next'"
      />
    </div>
    <VTable
      :columns="columns"
      :rows="currentPageRows"
      @sort-change="sortChangeHandler"
      :sortColumn="sortColumn"
      :sortOrder="sortOrder"
    />
  </div>
</template>

<script>
import VTable from '@/components/table/index.js'
import { ElPagination } from 'element-plus'

export default {
  name: 'example',
  components: {
    VTable,
    ElPagination
  },
  data() {
    return {
      columns: [
        { label: '姓名', prop: 'name', sortable: true },
        { label: '年龄', prop: 'age', sortable: true },
        { label: '性别', prop: 'gender' }
      ],
      rows: [
        { name: '小明', age: 18, gender: 1 },
        { name: '小红', age: 16, gender: 0 },
        { name: '小李', age: 20, gender: 1 },
        { name: '小白', age: 18, gender: 0 },
        { name: '小黄', age: 19, gender: 1 }
      ],
      sortColumn: '',
      sortOrder: 'ascending',
      currentPage: 1,
      pageSize: 3
    }
  },
  computed: {
    currentPageRows() {
      let start = (this.currentPage - 1) * this.pageSize
      let end = start + this.pageSize
      return this.rows.slice(start, end)
    }
  },
  methods: {
    sortChangeHandler(column) {
      if (column === this.sortColumn) {
        this.sortOrder = this.sortOrder === 'ascending' ? 'descending' : 'ascending'
      } else {
        this.sortColumn = column
        this.sortOrder = 'ascending'
      }
      this.sortRows()
    },
    sortRows() {
      this.rows.sort((row1, row2) => {
        let ascending = this.sortOrder === 'ascending' ? 1 : -1
        let descending = -ascending
        if (row1[this.sortColumn] > row2[this.sortColumn]) {
          return ascending
        } else if (row1[this.sortColumn] < row2[this.sortColumn]) {
          return descending
        } else {
          return 0
        }
      })
    }
  }
}
</script>

以上代码在示例1的基础上加入了分页功能,使用了Element Plus的分页组件。其中,计算属性currentPageRows根据当前页码和每页显示的数量计算出当前页需要展示的数据行,然后传入到VTable组件中进行渲染。如果用户点击了分页器上的上一页或下一页按钮,currentPage会得到更新,计算属性currentPageRows也会随之更新,自动渲染出新的表格。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue3新拟态组件库开发流程之table组件源码分析 - Python技术站

(0)
上一篇 2023年6月9日
下一篇 2023年6月9日

相关文章

  • Bootstrap基本插件学习笔记之模态对话框(16)

    Bootstrap基本插件学习笔记之模态对话框(16) 什么是模态对话框? 模态对话框(Modal)是一个会阻止用户输入的对话框,通常用于展示用户必须操作或者必须知道的信息。当出现模态对话框时,用户必须先完成对话框中的操作才能继续其他操作。 Bootstrap的模态对话框 Bootstrap的模态对话框是一种轻量级的、模态的(即阻止用户进行其他操作)对话框,…

    css 2023年6月9日
    00
  • css3中仿放大镜效果的几种方式原理解析

    针对“css3中仿放大镜效果的几种方式原理解析”这个话题,我可以分享一些完整的攻略,帮助你更好地了解。 实现原理 CSS3中实现放大镜效果一般有两种常用方式: 使用transform属性进行缩放:利用transform属性中的scale()函数,将需要放大的区域缩小至原始尺寸的比例,再为放大镜创建一个相同的区域进行放大。放大效果的实现依靠了scale()函数…

    css 2023年6月10日
    00
  • excel表格如何制作导航栏效果 制作导航栏切换效果的方法

    关于“excel表格如何制作导航栏效果 制作导航栏切换效果的方法”的完整攻略,我将为您提供以下的详细说明: 制作导航栏效果 首先,打开需要添加导航栏的excel表格,在第一行创建一个导航栏区域,例如B1:F1。 在导航栏区域中输入需要添加的导航链接名称,例如“首页”、“联系我们”等等。 选中导航栏区域,使用鼠标右键或者点击“开始”选项卡中的“格式为表格”按钮…

    css 2023年6月11日
    00
  • 所见即所得的富文本编辑器bootstrap-wysiwyg使用方法详解

    下面是关于“所见即所得的富文本编辑器bootstrap-wysiwyg使用方法详解”的完整攻略。 一、背景介绍 Bootstrap-wysiwyg是基于Bootstrap的富文本编辑器插件,拥有简洁、美观的界面和易用的功能,适用于各种网站开发中的文字、图像编辑等编辑要求。 二、安装与配置 1. 下载bootstrap-wysiwyg 从Github地址中下载…

    css 2023年6月9日
    00
  • css中filter属性和backdrop-filter的应用与区别详解

    CSS中filter属性和backdrop-filter的应用与区别详解 介绍 CSS中的filter属性和backdrop-filter属性可以用来修改元素的视觉效果。filter属性可以用于元素本身,而backdrop-filter属性用于元素背景。本文将详细介绍它们的使用方法。 filter属性 filter属性是CSS3中的一个属性,它能让你对元素的…

    css 2023年6月10日
    00
  • css全屏背景图片设置,django加载图片路径详解

    下面是“CSS全屏背景图片设置,Django加载图片路径详解”的完整攻略。 CSS全屏背景图片设置 在CSS中设置全屏背景图片有多种方式,其中比较常用的是使用background属性。下面是具体的步骤: 在CSS文件中选择要添加背景图片的元素,比如body元素。 使用background属性,将图片的路径和其他属性值作为background属性值进行设置。具…

    css 2023年6月9日
    00
  • 详解CSS中的Box Model盒属性的使用

    详解CSS中的Box Model盒属性的使用 什么是Box Model Box Model指的是CSS中盒模型,它用于定义HTML元素的组成部分以及在页面布局中的表现。一个HTML元素的盒模型主要包括以下几个部分: content box (内容区):HTML元素的实际内容,比如文字、图片、视频等等。 padding box (内边距区):与内容区相邻的空白…

    css 2023年6月10日
    00
  • css实现两栏布局,左侧固定宽,右侧自适应的多种方法

    请听我讲解。 1. float布局 使用 float 属性实现左侧固定宽度,右侧自适应的布局,具体的CSS样式如下: .container{ width: 100%; overflow: hidden; } .left{ width: 200px; float: left; margin-right: 10px; } .right{ overflow: hi…

    css 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部