Vue2+ElementUI列表、表格组件的封装

Vue2+ElementUI列表组件的封装:引言

在日常开发中,我们经常会遇到需要展示列表数据的场景。ElementUI 提供的 el-table 组件是一个功能强大的表格组件,可以满足大部分的需求。但是,在实际应用中,我们往往需要根据业务需求对 el-table 组件进行二次封装,以提高开发效率和代码的复用性。

本文将介绍 Vue2+ElementUI 列表组件的封装方法,包括:

  • 封装思路
  • 常见功能的实现
  • 代码示例
  • 注意点

封装思路
封装 el-table 组件的思路是将其作为一个独立的组件,对外暴露必要的属性和方法,并通过插槽机制来定制表格的内容。

具体来说,我们可以将 el-table 组件的封装分为以下几个步骤:

  1. 定义组件的 props,用于接收外部传入的数据和配置。
  2. 在组件内部,使用 el-table 组件来渲染表格。
  3. 通过插槽机制来定制表格的内容,例如表头、表尾、操作列等。
  4. 暴露一些方法,用于控制表格的操作,例如刷新、排序、筛选等。

创建组件模板并测试使用

创建组件,名为:H3yunTableCompV1,这是子组件

<template>
  <div>
    <el-table
        ref="multipleTable"
        tooltip-effect="dark"
        style="width: 100%"
    >
      <el-table-column
          type="index">
      </el-table-column>

    </el-table>
  </div>
</template>

<script>
export default {
  name: "H3yunTableCompV1",
  data() {
    return {}
  },
  methods: {}
}
</script>

<style scoped>

</style>

创建测试类并使用上面的组件,方便测试。注意:导入组件时注意路径。这是父组件。

<template>
  <div class="container" style="min-height: 100%; padding-bottom: 100px;">
    <H3yunTableCompV1></H3yunTableCompV1>
  </div>
</template>

<script>
import H3yunTableCompV1 from "../../components/table/H3yunTableCompV1";

export default {
  props: [],
  components: {
    H3yunTableCompV1
  },
  data() {
    return {}
  },
  watch: {},
  computed: {},
  beforeCreate() {
  },
  created() {
  },
  beforeMount() {
  },
  mounted() {
  },
  beforeUpdate() {
  },
  updated() {
  },
  destroyed() {
  },
  methods: {},
}
</script>

<style scoped>

.container {
}
</style>

父、子组件传值

父组件编写表格对象并传递给子组件。

<H3yunTableCompV1 :data="tableObj"></H3yunTableCompV1>


data() {
    return {
      // 这个对象可以从后端获取,下面是一些示例数据
      tableObj: {
        // 数据列 - 即el-table-column组件中的属性
        columns: [
          {prop: 'date', label: '日期', width: '180'},
          {prop: 'name', label: '名字', width: '180'},
          {prop: 'address', label: '地址', width: '180'}
        ]
      }
    }
  }

子组件接收值并处理

export default {
  name: "H3yunTableCompV1",
  data() {
    return {
      // 表格对象   -- 1
      tableObj: {
        columns: []
      }
    }
  },
  // 接收父组件传递过来的值
  props: {
    // 接收父组件传递过来的data数据,类型为Object   -- 2
    data: Object
  },
  watch: {
    // 监控父组件中的data,保证子组件中的tableObj与父组件一致   -- 3
    data: {
      deep: true, // 深度监控
      immediate: true, // 在组件创建时立即触发
      handler(newVal, oldVal) {
        this.init(newVal) // 初始化
      }
    }
  },
  methods: {
    // 初始化方法   -- 4
    init(newVal) {
      for (const key in newVal) {
        // 如果父组件传的值能与tableObj的属性匹配,比如父子组件都有tableObj.columns,则会进入这个if
        if (Object.keys(this.tableObj).includes(key)) {
          // 比如:tableObj.columns = newVal.columns
          this.tableObj[key] = newVal[key]
        }
      }

    }
  }
}

子组件循环 columns

<el-table
        ref="multipleTable"
        tooltip-effect="dark"
        style="width: 100%"
    >
      <el-table-column
          type="index">
      </el-table-column>
      <el-table-column
          v-for="(column,key) in tableObj.columns"
          :key="key"
          :prop="column.prop"
          :label="column.label"
          :width="column.width"
      >
      </el-table-column>
    </el-table>

效果如下

在这里插入图片描述

列隐藏

比如说我想隐藏ID列。我给id这个配置添加一个属性为hide:true

tableObj: {
        // 数据列 - 即el-table-column组件中的属性
        columns: [
          {prop: 'id', label: 'ID', width: '80', hide: true},
          {prop: 'date', label: '日期', width: '180'},
          {prop: 'name', label: '名字', width: '180'},
          {prop: 'address', label: '地址', width: '180'}
        ]
      }

id列未隐藏之前的效果。
在这里插入图片描述
子组件的el-table-column循环时加个属性v-if="!column.hide"。注意:这里使用v-show的话是不起作用的。

     <el-table-column
          v-for="(column,key) in tableObj.columns"
          :key="key"
          :prop="column.prop"
          :label="column.label"
          :width="column.width"
          v-if="!column.hide"
      >
      </el-table-column>

隐藏后的效果
在这里插入图片描述

插槽 - 文字链接

先看效果,标题列是通过插槽的方式插入的。

在这里插入图片描述

子组件使用v-if去判断是否是插槽去做分别处理。下面是完整的代码,里面使用了临时数据,后面会通过父组件传递。

<template>
  <div>
    <el-table
        ref="multipleTable"
        tooltip-effect="dark"
        style="width: 100%"
        :data="tableData"
        @selection-change="handleSelectionChange"
    >
      <!--多选-->
      <el-table-column
          type="selection"
          width="55">
      </el-table-column>
      <!--序号-->
      <el-table-column
          type="index">
      </el-table-column>
      <!--插槽处理-->
      <template v-for="(column,key) in tableObj.columns">
        <el-table-column
            :key="key"
            :prop="column.prop"
            :label="column.label"
            :width="column.width"
            v-if="column.type == 'slot'"
        >
          <template slot-scope="scope">
            <slot :name="column.slot_name" :row="scope.row"></slot>
          </template>
        </el-table-column>
        <el-table-column
            :key="key"
            :prop="column.prop"
            :label="column.label"
            :width="column.width"
            v-else-if="!column.hide"
        >
        </el-table-column>
      </template>


    </el-table>
  </div>
</template>

<script>
export default {
  name: "H3yunTableCompV1",
  data() {
    return {
      // 表格对象   -- 1
      tableObj: {
        columns: []
      },
      tableData: [{
        id: 1,
        title: '标题1',
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄',
        tag: '家'
      }, {
        id: 2,
        title: '标题2',
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄',
        tag: '公司'
      }, {
        id: 3,
        title: '标题3',
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 弄',
        tag: '家'
      }]
    }
  },
  // 接收父组件传递过来的值
  props: {
    // 接收父组件传递过来的data数据,类型为Object   -- 2
    data: Object
  },
  watch: {
    // 监控父组件中的data,保证子组件中的tableObj与父组件一致   -- 3
    data: {
      deep: true, // 深度监控
      immediate: true, // 在组件创建时立即触发
      handler(newVal, oldVal) {
        this.init(newVal) // 初始化
      }
    }
  },
  methods: {
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    // 初始化方法   -- 4
    init(newVal) {
      for (const key in newVal) {
        // 如果父组件传的值能与tableObj的属性匹配,比如父子组件都有tableObj.columns,则会进入这个if
        if (Object.keys(this.tableObj).includes(key)) {
          // 比如:tableObj.columns = newVal.columns
          this.tableObj[key] = newVal[key]
        }
      }

    }
  }
}
</script>

<style scoped>

</style>


父组件使用templatev-slot:插槽名去处理插槽。这里是拿到了整行数据而不仅仅是title这一列,里面的内容完全是自定义的。

<H3yunTableCompV1 :data="tableObj">
      // 处理标题插槽
      <template v-slot:title_slot="scope">
        <el-link type="primary">{{ scope.row.title }}</el-link>
      </template>
</H3yunTableCompV1>

export default {
components: {
    H3yunTableCompV1
  },
  data() {
    return {
      // 这个对象可以从后端获取,下面是一些示例数据
      tableObj: {
        // 数据列 - 即el-table-column组件中的属性
        columns: [
          {prop: 'title', label: '标题', width: '180', type: 'slot', slot_name: 'title_slot'}, // 定义标题列是插槽
          {prop: 'date', label: '日期', width: '180'},
          {prop: 'name', label: '名字', width: '180'},
          {prop: 'address', label: '地址', width: '180'}
        ]
      }
    }
  }
}

插槽 - 按钮

注意:插槽 - 按钮这个示例是在上一个示例的基础上的。

效果如下:

在这里插入图片描述

增加列,并定义插槽的名称为operate_slot

{prop: 'operate', label: '操作', width: '180', type: 'slot', slot_name: 'operate_slot'}

在这里插入图片描述插槽处理

    <H3yunTableCompV1 :data="tableObj">
      // 标题 - 插槽
      <template v-slot:title_slot="scope">
        <el-link type="primary">{{ scope.row.title }}</el-link>
      </template>
      // 操作 - 插槽
      <template v-slot:operate_slot="scope">
        <el-button-group>
          <el-button type="primary" disabled>编辑</el-button>
          <el-button type="primary" disabled>删除</el-button>
        </el-button-group>
      </template>
    </H3yunTableCompV1>

分页

效果如下:在这里插入图片描述
代码改动比较多,下面直接上代码。

父组件如下,主要增加与后端联动。

<template>
  <div class="container" style="min-height: 100%; padding-bottom: 100px;">
    <H3yunTableCompV1 :data="tableObj">
      // 标题 - 插槽
      <template v-slot:fnsku_slot="scope">
        <el-link type="primary">{{ scope.row.fnsku }}</el-link>
      </template>
      // 操作 - 插槽
      <template v-slot:operate_slot="scope">
        <el-button-group>
          <el-button type="primary" disabled>编辑</el-button>
          <el-button type="primary" disabled>删除</el-button>
        </el-button-group>
      </template>
    </H3yunTableCompV1>
  </div>
</template>

<script>
import H3yunTableCompV1 from "../../components/table/H3yunTableCompV1";

export default {
  props: [],
  components: {
    H3yunTableCompV1
  },
  data() {
    return {
      // 这个对象可以从后端获取,下面是一些示例数据
      tableObj: {
        http: {
          // 这个url你们需要写成完整的url
          url: '/logisticSalesPrediction/list',
          params: {},
          // url返回结果的数据结构,
          result: {
            // 表格内容表示是在result.records中获取
            list: 'records',
            // 数据量总数是在result.total中获取
            total: 'total'
          }
        },
        pageNum: 1,
        pageSize: 10,
        total: 0,
        // 数据列 - 即el-table-column组件中的属性
        columns: [
          {prop: 'fnsku', label: 'fnsku', width: '180', type: 'slot', slot_name: 'fnsku_slot'}, // 定义标题列是插槽
          {prop: 'isSeason', label: '是否是时令性产品', width: '180'},
          {prop: 'activityIncrement', label: '活动增量', width: '180'},
          {prop: 'prediction', label: '销量预测', width: '180'},
        ]
      }
    }
  },
  methods: {},
}
</script>

<style scoped>

.container {
}
</style>

下面是子组件的代码。

首先,在table标签下面增加了分页组件,其次增加了axios的请求,与响应结果的处理。细节部分呢,就是切换页码,页大小和序号。

<template>
  <div>
    <el-table
        ref="multipleTable"
        tooltip-effect="dark"
        style="width: 100%"
        :data="tableData"
        @selection-change="handleSelectionChange"
    >
      <!--多选-->
      <el-table-column
          type="selection"
          width="55">
      </el-table-column>
      <!--序号-->
      <el-table-column
          type="index"
          :index="calIndex"
      >
      </el-table-column>
      <!--插槽处理-->
      <template v-for="(column,key) in tableObj.columns">
        <el-table-column
            :key="key"
            :prop="column.prop"
            :label="column.label"
            :width="column.width"
            v-if="column.type == 'slot'"
        >
          <template slot-scope="scope">
            <slot :name="column.slot_name" :row="scope.row"></slot>
          </template>
        </el-table-column>
        <el-table-column
            :key="key"
            :prop="column.prop"
            :label="column.label"
            :width="column.width"
            v-else-if="!column.hide"
        >
        </el-table-column>
      </template>
    </el-table>
    <div>
      <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="tableObj.pageNum"
          :page-sizes="[10, 20, 50, 100]"
          :page-size="tableObj.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="tableObj.total">
      </el-pagination>
    </div>

  </div>
</template>

<script>

import request from "../../utils/request";

export default {
  name: "H3yunTableCompV1",
  data() {
    return {
      // 表格对象   -- 1
      tableObj: {
        http: {
          url: undefined,
          params: {},
          result: {
            list: undefined,
            total: undefined
          }
        },
        pageNum: 1,
        pageSize: 10,
        total: 0,
        columns: []
      },
      tableData: []
    }
  },
  // 接收父组件传递过来的值
  props: {
    // 接收父组件传递过来的data数据,类型为Object   -- 2
    data: Object
  },
  watch: {
    // 监控父组件中的data,保证子组件中的tableObj与父组件一致   -- 3
    data: {
      deep: true, // 深度监控
      immediate: true, // 在组件创建时立即触发
      handler(newVal, oldVal) {
        this.init(newVal) // 初始化
      }
    }
  },
  // 挂载之前加载数据
  beforeMount() {
    this.load()
  },
  methods: {
    // 计算序号
    calIndex(index) {
      return (this.tableObj.pageNum - 1) * (this.tableObj.pageSize) + index + 1
    },
    // 构建查询参数
    buildParams() {
      const params = this.tableObj.http.params
      params.pageNum = this.tableObj.pageNum
      params.pageSize = this.tableObj.pageSize
      return params
    },
    // 解析构建结果 - 为了适配 list: 'data.records',做一下处理
    buildResult(data, key) {
      const keys = key.split('.')
      let res = data
      for (const key of keys) {
        res = res[key]

      }
      return res
    },
    // 加载后端数据
    load() {
      // request对axios进行了一层封装
      request.post(this.tableObj.http.url, this.buildParams()).then(pageObj => {
        // 后端返回结果,需要的字段在哪不写死
        this.tableData = this.buildResult(pageObj, this.tableObj.http.result.list)
        this.tableObj.total = this.buildResult(pageObj, this.tableObj.http.result.total)
      })
    },
    // 更改每页数量
    handleSizeChange(val) {
      this.tableObj.pageSize = val
      this.tableObj.pageNum = 1
      this.load()
    },
    // 页码切换
    handleCurrentChange(val) {
      this.tableObj.pageNum = val
      this.load()
    },
    // 多选
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    // 初始化方法   -- 4
    init(newVal) {
      for (const key in newVal) {
        // 如果父组件传的值能与tableObj的属性匹配,比如父子组件都有tableObj.columns,则会进入这个if
        if (Object.keys(this.tableObj).includes(key)) {
          // 比如:tableObj.columns = newVal.columns
          this.tableObj[key] = newVal[key]
        }
      }

    }
  }
}
</script>

<style scoped>

</style>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/427947.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【嵌入式——QT】QTreeWidget

QTreeWidget类是创建和管理目录树结构的类&#xff0c;QTreeWidget每一个节点都是一个QTreeWidgetItem对象&#xff0c;添加一个节点前需先创建。QTreeWidget类是一个便利类&#xff0c;它提供了一个标准的树widget&#xff0c;具有经典的基于item的界面&#xff0c;类似于Qt 3…

2024智能遥控器行业市场规模及技术水平分析

智能遥控器&#xff0c;主要是由集成电路板和用来生产不同讯息的按钮所组成&#xff0c;内装有一个中央处理器芯片&#xff0c;芯片在制造时就将设备各种菜单码值信息输入其中&#xff0c;遥控发射器只要发出与之对应的密码就可以实现对设备的控制。无线遥控技术原理就是发射机…

【kubernetes】关于k8s集群的污点和容忍,以及k8s集群的故障排查思路

目录 一、污点 关于污点的增删改查 验证污点的作用——NoExecute ​编辑 验证污点的作用——NoSchedule 验证污点的作用——PreferNoSchedule 二、容忍 三、关于cordon 和 drain 四、Pod启动阶段 五、关于pod的五种状态 六、k8s常见的排障手段 针对组件故障 针对pod…

短视频直播电商项目运营建设规划方案商业计划

【干货资料持续更新&#xff0c;以防走丢】 短视频直播电商项目运营建设规划方案商业计划 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PPT&#xff08;完整资料包含以下内容&#xff09; 目录 短视频直播运营方案 一、云零售电商运营体系搭建&#xff1a; …

Arduino与processing之间的通信——进阶版

本次需要实现Arduino获取板子的偏转角度并通过串口发送给processing&#xff0c;processing部分根据传输过来的各个轴的偏转角度建立对应偏转角度的3D模型。 这就涉及了两个轴正负方向的偏转&#xff0c;我的实现思路是使用串口传输 字母数字 格式的信息&#xff0c;字母用来判…

如何在手机上中恢复已删除的照片

市场上有大量用于恢复手机已删除照片的应用程序。您可以尝试任何合法的应用程序来恢复意外删除的视频。其中一些应用程序包括 奇客数据恢复、Disk Drill等。 恢复已删除的 Android 照片 如果您不小心从 Android 设备中删除了任何重要视频&#xff0c;无需惊慌。您可以按照这些…

滑动窗口

题目 思路 对于一个数组区间的最值&#xff0c;可以开辟一个队列记录&#xff08;当然这里不能叫队列只是和队列相似&#xff0c;习惯性叫法)。 每个区间的最值等于队首元素。扫描数组时&#xff0c;如果该元素大于队尾元素&#xff08;取最大值时&#xff09;将该队尾元素出队…

利用Python爬取高德地图全国地铁站点信息

利用Python中的requests库进行地铁站点信息的获取,同时将数据保存在本机excel中 # 首先引入所需要的包 import requests from bs4 import BeautifulSoup import pandas as pd import json# 发送 GET 请求获取网页内容 url http://map.amap.com/subway/index.html response r…

06.QT信号和槽-1

一、信号和槽概述 在Qt中&#xff0c;用户和控件的每次交互过程称为一个事件。比如"用户点击按钮"是一个事件&#xff0c;"用户关闭窗口"也是一个事件。每个事件都会发出一个信号&#xff0c;例如用户点击按钮会发出"按钮被点击"的信号&#xff…

Ubuntu的apt、apt-get和apt-cache命令

原文&#xff1a;apt 和 apt-get 之间有什么区别&#xff1f; https://aws.amazon.com/cn/compare/the-difference-between-apt-and-apt-get/ 陈拓转载&#xff0c;2023/11/23&#xff0c;添加了举例。 apt 和 apt-get 之间有什么区别&#xff1f; apt 和 apt-get 都是命令行…

三位数反转问题易被忽略的两大细节

【题目描述】 输入一个三位数&#xff0c;分离出它的百位、十位和个位&#xff0c;反转后输出。 【样例输入】 127 【样例输出】 721 这个问题并不难&#xff0c;只需要两步&#xff1a; ①将这个三位数分离成三个数字&#xff08;参见“整数的分离与合成”一文&#xff…

lv20 QT事件5

1 事件模型 2 事件处理 virtual void keyPressEvent(QKeyEvent *event) virtual void keyReleaseEvent(QKeyEvent *event) virtual void mouseDoubleClickEvent(QMouseEvent *event) virtual void mouseMoveEvent(QMouseEvent *event) virtual void mousePressEvent(QMou…

【大厂AI课学习笔记NO.59】(12)过拟合与欠拟合

拟合就是调整参数和模型&#xff0c;让结果无限接近真实值的过程。 我们先来了解个概念&#xff1a; 偏差-方差窘境&#xff08;bias-variance dilemma&#xff09;是机器学习中的一个重要概念&#xff0c;它涉及到模型选择时面临的权衡问题。 偏差&#xff08;Bias&#xf…

自建Redis蜜罐以捕获和分析潜在攻击

一、引言 随着网络攻击的日益频繁和复杂&#xff0c;传统的防御措施往往难以应对。蜜罐作为一种主动防御技术&#xff0c;通过模拟有价值的服务来吸引攻击者&#xff0c;从而收集和分析攻击数据&#xff0c;提高网络安全性。本文将介绍如何自建一个Redis蜜罐&#xff0c;以捕获…

转转测试环境docker化实践

【软件测试面试突击班】2024吃透软件测试面试最全八股文攻略教程&#xff0c;一周学完让你面试通过率提高90%&#xff01;&#xff08;自动化测试&#xff09; 测试环境对于任何一个软件公司来讲&#xff0c;都是核心基础组件之一。转转的测试环境伴随着转转的发展也从单一的几…

【开源】JAVA+Vue.js实现农家乐订餐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户2.2 管理员 三、系统展示四、核心代码4.1 查询菜品类型4.2 查询菜品4.3 加购菜品4.4 新增菜品收藏4.5 新增菜品留言 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的农家乐订餐系统&#xff0c…

MS1030超声波流量高精度测量电路

产品简述 MS1030 是一款针对超声波流量高精度测量电路&#xff0c;它具有高 精度&#xff0c;高稳定性&#xff0c;高效率的特点。它的测量精度 15ps &#xff0c;测量范 围 500ns  4ms4MHz 。在第一波模式情况下&#xff0c;内部比较器的 offset 可编程范围为 127…

type.GetFields() 获取不到,改用type.DeclaredFields

StatisticQuery 类 private Dictionary<string, DateTime> GetTBHBDate(StatisticQuery model, string field){Dictionary<string, DateTime> dic new Dictionary<string, DateTime>();DateTime TB new DateTime();//同比开始日期 &#xff08;年&#xff…

计网面试题整理下

1. HTTP常见的状态码有哪些&#xff1f; 常见状态码&#xff1a; 200&#xff1a;服务器已成功处理了请求。 通常&#xff0c;这表示服务器提供了请求的网页。301 &#xff1a; (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时&am…

揭秘测试工程师的6大必备技能!你也常遇到这个问题吗?

作为一名Tester&#xff0c;无论是面试还是工作&#xff0c;我们都常常会遇到该问题&#xff0c;毕竟现在大部分接手的项目都是中小型的项目&#xff0c;很多又是生疏行业的系统&#xff0c;所以这个问题就会常常伴随我们&#xff0c;那么遇到这个问题该怎么办呢&#xff0c;现…