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

news2024/11/15 22:42:15

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>


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python | Conda安装包报错:PackagesNotFoundError

Conda在下载安装包时报错&#xff1a; PackagesNotFoundError: The following packages are not available from current channels:- XXXXXX&#xff08;包名&#xff09;有如下两种解决方法&#xff1a; 方法一&#xff1a;将conda-forge添加到搜索路径上 在命令行运行下方指令…

spring cloud 之 Netflix Eureka

1、Eureka 简介 Eureka是Spring Cloud Netflix 微服务套件中的一个服务发现组件&#xff0c;本质上是一个基于REST的服务&#xff0c;主要用于AWS云来定位服务以实现中间层服务的负载均衡和故障转移,它的设计理念就是“注册中心”。 你可以认为它是一个存储服务地址信息的大本…

14-RPC-自研微服务框架

RPC RPC 框架是分布式领域核心组件&#xff0c;也是微服务的基础。 RPC &#xff08;Remote Procedure Call&#xff09;全称是远程过程调用&#xff0c;相对于本地方法调用&#xff0c;在同一内存空间可以直接通过方法栈实现调用&#xff0c;远程调用则跨了不同的服务终端&a…

游戏框架搭建

使用框架的目标&#xff1a;低耦合&#xff0c;高内聚&#xff0c;表现和数据分离 耦合&#xff1a;对象&#xff0c;类的双向引用&#xff0c;循环引用 内聚&#xff1a;相同类型的代码放在一起 表现和数据分离&#xff1a;需要共享的数据放在Model里 对象之间的交互一般有三…

XUbuntu22.04之显示实时网速(二百一十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【字符串】马拉车(Manacher)算法

本篇文章参考&#xff1a;比较易懂的 Manacher&#xff08;马拉车&#xff09;算法配图详解 马拉车算法可以求出一个字符串中的最长回文子串&#xff0c;时间复杂度 O ( n ) O(n) O(n) 因为字符串长度的奇偶性&#xff0c;回文子串的中心可能是一个字符&#xff0c;也可能是…

智慧草莓基地:Java与SpringBoot的技术革新

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

ue4.27 发现 getRandomReachedLocation 返回 false

把这个玩意儿删掉&#xff0c;重启工程&#xff0c;即可 如果还不行 保证运动物体在 volum 内部&#xff0c;也就是绿色范围内确保 project setting 里面的 navigation system 中 auto create navigation data 是打开的(看到过博客说关掉&#xff0c;不知道为啥) 如果还不行&…

STM32学习和实践笔记(1): 装好了的keil μVision 5

2019年3月在淘宝上买了这块STM32的开发板&#xff0c;学了一段时间后就丢下了&#xff0c;今天重新捡起来&#xff0c;决定好好学习、天天向上。 对照教程&#xff0c;今天先把keil5装上了。 装的过程有以下几点值得记录下&#xff1a; 1&#xff09;用注册机时&#xff0c;…

【数据结构】B树

1 B树介绍 B树&#xff08;英语&#xff1a;B-tree&#xff09;&#xff0c;是一种在计算机科学自平衡的树&#xff0c;能够保持数据有序。这种数据结构能够让查找数据、顺序访问、插入数据及删除的动作&#xff0c;都在对数时间内完成。B树&#xff0c;概括来说是一个一般化的…

波斯猫 6页面 宠物动物 长毛猫 HTML5 带背景音乐 JS图片轮播特效 滚动文字 鼠标经过图片 JS时间代码

波斯猫 6页面 宠物动物 长毛猫 HTML5 带背景音乐 JS图片轮播特效 滚动文字 鼠标经过图片 JS时间代码 注册表单 宠物网页成品 海量学生网页成品 个人博客 人物明星 城市家乡 旅游景点 美食特产 购物电商 公司企业 学校大学 科普教育 宠物动物 鲜花花卉 植物水果 茶叶咖啡 健康生…

【前端寻宝之路】学习如何使用HTML实现简历展示和填写

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-iJ3Ou0qMGFVaqVQq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

Google Dremel和parquet的复杂嵌套数据结构表征方法解析

转载请注明出处。作者&#xff1a;archimekai 核心参考文献&#xff1a; Dremel: Interactive Analysis of Web-Scale Datasets 文章目录 引言复杂嵌套数据结构的无损表征问题Dremel论文中提出的表征方法parquet备注 引言 Dremel是Google的交互式分析系统。Google大量采用prot…

LabVIEW石油钻机提升系统数字孪生技术

LabVIEW石油钻机提升系统数字孪生技术 随着数字化、信息化、智能化的发展&#xff0c;石油钻采过程中的石油钻机数字化技术提升成为了提高钻井效率、降低生产成本的重要途径。基于中石油云平台提供的数据&#xff0c;采用数字孪生技术&#xff0c;对石油钻机提升系统进行数字化…

设计模式(十三)抽象工厂模式

请直接看原文:设计模式&#xff08;十三&#xff09;抽象工厂模式_抽象工厂模式告诉我们,要针对接口而不是实现进行设计。( )-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- …

Some collections -- 2024.3

一、TensorFlow Android (dataset: Mnist) We used TensorFlow to define and train our machine learning model, which can recognize handwritten numbers, called a number classifier model in machine learning terminology. We transform the trained TensorFlow mod…

pytest-allure报告生成

pytest生成allure报告步骤&#xff1a; 下载allure&#xff0c;配置allure报告的环境变量&#xff1a;把allure-2.13.7\bin 配置到环境变量path路径 验证&#xff1a;在dos窗口和pycharm窗口分别验证&#xff1a;allure –version 2. 生成临时的json报告 在pytest.ini配置文…

挑战杯 基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

【k8s管理--可视化界面】

1、可视化界面的软件 kubernetes的可视化软件有以下这些kubernetes dashboard&#xff1a;https://github.com/kubernetes/dashboardkubesphere官网&#xff1a; https://kubesphere.io/zh/rancher 官网&#xff1a; https://www.rancher.cn/kuboard 官网&#xff1a; https:/…

基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的数码管显示应用

基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的数码管显示应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍TM1638键盘数码管模块概述TM1638键盘数码管…