慢慢推倒一座屎山——代码结构的部分优化

286 阅读3分钟

近期由于公司有一个老项目升级改造,要调整大量样式。本来以为是一件很轻松的活,没想到最后身心俱疲。丑陋不堪的样式,缺乏规范导致的无法统一修改共有的颜色、样式等,相同的布局没有提取出来,每个页面都是复制的,搞得很累,所以打算调整一下。因为是一个偏向于后台系统的前端项目,就从基础的表格开始,基于element浅浅的写了一个表格组件和分页组件

由于表格+分页在很多页面都用到了,按照传统的写法的话每个用到的地方都要加一个element的表格和它的分页组件,一两个还好,多了就很烦,因此写了两个组件配合着使用,用的时候如下图。

image.png

上面的表格组件用来展示数据,下面的分页负责加载数据。不是很完善,但现阶段来说够用。

首先是表格组件很明显比element默认的那种使用方式在肉眼可见的dom上简洁了一些,当时也是考虑到如果表格存在大量展示字段以及自定义展示内容的时候整个dom结构是会比较乱的,所以采用了配置项的方法来循环创建表格的列。图中 col属性就是用来传入列的。传入的列如下图,其中prop表示返回数据对应的字段名,label表示表头的名字。slot表示这一列需要插槽,用来传入当前列所需的操作。

image.png

下面是表格内部的代码

image.png

<template>
  <el-table :data="data" :height="height" style="width: 100%">
    <el-table-column
      label="序号"
      align="center"
      type="index"
      width="60px"
      show-overflow-tooltip
      :index="indexMethod"
      v-if="showIndex"
    ></el-table-column>

    <el-table-column
      v-for="(item, index) in col"
      :key="index"
      :prop="item.prop"
      :label="item.label"
      :align="item.center?item.center:'center'"
      :show-overflow-tooltip="!item.noHidden"
      :width="item.width || 'auto'"
    >
      <template v-if="item.slot" v-slot="{ row }">
        <slot :name="item.prop" :row="row"></slot>
      </template>
    </el-table-column>
  </el-table>
</template>
<script>
export default {
  props: {
    data: {
      type: Array,
      default() {
        return [];
      },
    },
    pageIndex: {
      type: Number,
      default: 1,
    },
    pageSize: {
      type: Number,
      default: 10,
    },
    height: {
      type: String,
      default: "400px",
    },
    showIndex: {
      type: Boolean,
      default: true,
    },
    col: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      showTip: true,
    };
  },
  methods: {
    indexMethod(index) {
      return (this.pageIndex - 1) * this.pageSize + index + 1;
    },
  
  },
};
</script>

默认是存在index列的,可通过传入 showIndex属性来控制是否有序号列。 用了具名插槽往外传递数据以便于外边传入的可以获取的组件内部当前列的数据,具名插槽的名字就是传入的字段属性名称。并且为插槽绑定数据。如这块只是不了解可以去vue官网看v2关于插槽部分的文档。

如果在外部需要传入插槽的话,只需要如下使用就好

image.png

下面是分页组件

image.png

分页组件的使用方法很简单。只需要给一个ref , 绑定写好的获取数据的方法就好。 代码如下

<template>
  <el-pagination
    background
    layout="total,sizes,prev, pager, next,jumper"
    :total="total"
    @size-change="handleSizeChange"
    @current-change="handleIndexChange"
    :page-sizes="pageSizes"
  >
  </el-pagination>
</template>

<script>
export default {
  name: "fenYe",
  props: {
    query: {
      type: Function,
      default: null,
    },
    auto: {
      type: Boolean,
      default: true,
    },
    pageSizes: {
      type: Array,
      default() {
        return [10, 30, 50];
      },
    },
  },
  data() {
    return {
      pageIndex: 1,
      pageSize: 10,
      total: 0,
    };
  },
  mounted() {
    if (this.auto) {
      this.query(this.pageIndex, this.pageSize);
    }
  },
  methods: {
    handleIndexChange(val) {
      console.log("页码变化", val);
      this.pageIndex = val;
      this.query(this.pageIndex, this.pageSize);
    },
    handleSizeChange(val) {
      console.log("数量变化", val);
      this.pageSize = val;
      this.query(this.pageIndex, this.pageSize);
    },
    //重置页码为1查询
    reload() {
      this.pageIndex = 1;
      this.query(this.pageIndex, this.pageSize);
    },
    //重新加载当前页码
    reFresh() {
      this.query(this.pageIndex, this.pageSize);
    },
    setTotal(total) {
      this.total = total;
    },
  },
};
</script>

<style>
</style>

这个组件在加载完毕后如果auto为true的情况下会自动调用传入的方法加载数据,并且维护页码和当前页的请求数量。提供了三个方法通过this.$refs.xx.xx()调用。只需要在传入的方法中接收pageIndex和pageSize两个参数即可。如下

image.png 与table结合使用将这两个参数组合成pageInfo对象传入即可计算好序号。 到这里这两个组件能满足大部分的基础场景,剩余场景用到了再继续补充,扩充起来也比较方便。推倒屎山第一步就好了。