Element-ui二次封装一个带图片展示的高通用性table表格

使用Element-ui框架也很久了,最近项目中有个应用场景,如下图示:
在这里插入图片描述
在这里插入图片描述
如上截图,在这个table表格中,有显示类文本,有image图片,有switch开关,还有数据编辑操作列。
话不多说,开撸:
首先,在项目文件夹的components中新建CommonTable.bue文件,先生成一个标准的vue页面模板:

<template>
    <div>
		
    </div>
</template>

<script>
    export default {
        
    }
</script>

<style lang="scss" scoped>

</style>

下面,我们去把element-ui中复制table组件源码,然后针对这个源码进行2次改造,建议对组件中的自定义列模板复制哦:
在这里插入图片描述

<template>
    <el-table :data="tableData" style="width: 100%" v-loading="config.loading">
    	<!-- 这里是对tableLableList列表中的字段进行过滤,处理image字段 -->
      <el-table-column
        v-for="item in tableLabelList.filter(el => el.prop === 'image')"
        :key="item.prop"
        show-overflow-tooltip
        :label="item.label"
        :width="item.width ? item.width : 75"
      >
        <template slot-scope="scope">
          <span style="margin-left: 10px">
            <img
              :src="scope.row.imageUrl"
              alt=""
              style="width:100px;height:100px"
            />
          </span>
        </template>
      </el-table-column>
	  <!-- 这里对常规文本类型进行处理,对过滤出image和switch之后的字段进行循环绑定 -->
	  <el-table-column
        v-for="item in tableLabelList.filter(
          ele => ele.prop !== 'image' && ele.prop !== 'status'
        )"
        :key="item.prop"
        :label="item.label"
        :width="item.width ? item.width : 180"
      >
        <template slot-scope="scope">
          <span style="margin-left:10px">{{ scope.row[item.prop] }}</span>
        </template>
      </el-table-column>
	
	<!-- 处理switch开关 -->
	<el-table-column
        v-for="item in tableLabelList.filter(ele => ele.prop === 'status')"
        :key="item.prop"
        :label="item.label"
        :width="item.width ? item.width : 50"
      >
        <template slot-scope="scope">
            <!-- switch开关:之所以disableed,是不希望在这里进行状态修改,而是通过编辑的方式提交post请求修改 -->
            <el-switch disabled v-model="scope.row.status"></el-switch>
        </template>
      </el-table-column>	
    </el-table>
	
	<!--数据操作列,可以根据实际情况进行逻辑处理 -->
	<el-table-column label="操作">
        <template slot-scope="scope">
          <el-button size="mini" @click="handleEdit(scope.$index, scope.row)"
            >编辑</el-button
          >
          <el-button
            size="mini"
            type="danger"
            @click="handleDelete(scope.$index, scope.row)"
            >删除</el-button
          >
        </template>
      </el-table-column>
</template>

<script>
    export default {
  		// 接收父组件传参
        props: {
        	tableData: Array, // 存放父组件传递过来的表数据
        	tableLabelList: Array, // 存放父组件传递过来的表字段数据
        	config:Object	// 配置项,比如表格每一页多少条数据,数据的加载状态,v-loading指令
        },
        methods: {
            handleEdit(index, row) {
                console.log(index, row);
            },
            handleDelete(index, row) {
                console.log(index, row);
           }
    }
    }
</script>
<style lang="scss" scoped>
</style>

上面是整个table组件的完成代码,为了不至于篇幅太长影响阅读,我把二次封装不同类型的代码分开放在下面:

  • 封装表格项中的img图片:
	<el-table-column
        v-for="item in tableLabelList.filter(el => el.prop === 'image')"
        :key="item.prop"
        show-overflow-tooltip
        :label="item.label"
        :width="item.width ? item.width : 75"
      >
        <template slot-scope="scope">
          <span style="margin-left: 10px">
            <img
              :src="scope.row.imageUrl"
              alt=""
              style="width:100px;height:100px"
            />
          </span>
        </template>
      </el-table-column>
  • 封装常规的文本类型:
<el-table-column
        v-for="item in tableLabelList.filter(
          ele => ele.prop !== 'image' && ele.prop !== 'status'
        )"
        :key="item.prop"
        :label="item.label"
        :width="item.width ? item.width : 180"
      >
        <template slot-scope="scope">
          <span style="margin-left:10px">{{ scope.row[item.prop] }}</span>
        </template>
</el-table-column>
  • 封装switch开关:
<el-table-column
        v-for="item in tableLabelList.filter(ele => ele.prop === 'status')"
        :key="item.prop"
        :label="item.label"
        :width="item.width ? item.width : 50"
      >
        <template slot-scope="scope">
            <!-- switch开关:之所以disableed,是不希望在这里进行状态修改,而是通过编辑的方式提交post请求修改 -->
            <el-switch disabled v-model="scope.row.status"></el-switch>
        </template>
      </el-table-column>	

注意,我这里的处理逻辑是通过判断tableLabelList表头的prop属性,过滤出tableLabelList中不同的表头,处理不同的类型。

既然上面已经二次封装好了,那么就去使用吧:
例如,我这里在GoodsManager.vue页面中引入CommonTable组件:

<script>
// 引入组件
import CommonTable from "@/components/CommonTable"
export default{
	//2、注册组件
	components:{
		CommonTable,	// 实际上是: CommonTable:CommonTable,key和value一致时可以省略
	}
}
</script>

使用组件和传参:

	<!-- 在需要使用CommonTable表格的地方-->
	 <common-table
	 	<!-- 传参-->
          :tableData="saleList"
          :tableLabel="tableLabel"
          :config="config"
        ></common-table>

数据如下,在data下初始化数据:

data(){
	return{
		config: {
        page: 1,
        total: 20,
        loading: false //加载数据
        },
		tableLabel: [
        {
          prop: 'image',
          label: '图片',
          type: 'image',
          width: 200
        },
        {
          prop: 'label',
          label: '商品名称',
          width: 300
        },
        {
          prop: 'ficti',
          label: '虚拟销量'
        },
        {
          prop: 'stock',
          label: '库存'
        },
        {
          prop: 'sales',
          label: '销量'
        },
        {
          prop: 'status',
          label: '状态'
        }
  		],
  		// tableData
  		tableData:[
			{
    type: 1,
    label: '德尔玛家用床上除螨仪/吸尘器杀菌净化45min续航一体收纳充电CM2000白色',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/33fb5f29f0f52236a85831c8655b9bde.jpg',
    ficti: 20,
    price: 299,
    classify: '卫浴清洁',
    stock: 10000,
    sales: 68,
    status: true,
    unit_name: '件',
    keywords: ''
  },
  {
    type: 2,
    label: '云麦体脂秤称重女智能精准成人脂肪测量仪家用电子体重秤',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/fb40e23473563d0853bb02bc4baa2ea2.jpg',
    ficti: 30,
    price: 99,
    classify: '日用杂货',
    stock: 0,
    sales: 90,
    status: true,
    unit_name: '台',
    keywords: ''
  },
  {
    type: 1,
    label:
      '荣耀20青春版 AMOLED屏幕指纹 4000mAh大电池 20W快充 4800万 手机 6GB+64GB 冰岛幻境',
    image:
      'http://demo26.crmeb.net/uploads/attach/2020/04/27/b2bf3cf3be8a983c1920da54fb9f8579.jpg',
    ficti: 22,
    price: 2699,
    classify: '数码产品',
    stock: 800,
    sales: 10,
    status: true,
    unit_name: '台',
    keywords: ''
  },
  {
    type: 2,
    label: '【超品预售】TOMFORD汤姆福特唇膏4色TF口红黑管套装礼盒16',
    image:
      'http://demo26.crmeb.net/uploads/attach/2020/04/24/7092e35b87c2849b5f7c48b3e8175f98.jpg',
    ficti: 10,
    price: 399,
    classify: '彩妆香氛',
    stock: 30,
    sales: 10,
    status: false,
    unit_name: '件',
    keywords: ''
  },
  {
    type: 1,
    label: '极蜂天文望远镜天地两用可连接手机拍照望远镜观星星观月亮观景白色',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/759a8317831bbcf71d199277d2f3a8ce.jpg',
    ficti: 10,
    price: 399,
    classify: '数码产品',
    stock: 20,
    sales: 10,
    status: false,
    unit_name: '件',
    keywords: ''
  },
  {
    type: 2,
    label: '心想智能胶囊咖啡机S1102智能全自动手机APP可调2种模式',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/824200dd43d4eb8e7c185993c82b54ad.jpg',
    ficti: 10,
    price: 1999,
    classify: '数码产品',
    stock: 0,
    sales: 10,
    status: false,
    unit_name: '件',
    keywords: ''
  },
  {
    type: 1,
    label: '莱克吉米手持无线吸尘器除螨除尘组合家用大吸力静音',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/2a21667934bd7e26c7edd02687efdd34.jpg',
    ficti: 10,
    price: 499,
    classify: '卫浴清洁',
    stock: 400,
    sales: 10,
    status: false,
    unit_name: '件',
    keywords: ''
  },
  {
    type: 1,
    label: '火候进口整木砧板乌檀木实木家用厨房菜板防霉切菜板',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/4b77ed78767c49b05d365d01b1d95d99.jpg',
    ficti: 10,
    price: 499,
    classify: '日用杂货',
    stock: 50,
    sales: 10,
    status: false,
    unit_name: '件',
    keywords: ''
  },
  {
    type: 1,
    label: '本来设计挂钟原木时钟创意现代简约实木北欧客厅卧室钟表',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/fd79a0af5d4a3eda1572cae99f6725c5.jpg',
    ficti: 10,
    price: 499,
    classify: '日用杂货',
    stock: 30,
    sales: 10,
    status: false,
    unit_name: '件',
    keywords: ''
  },
  {
    type: 2,
    label: '本来设计挂钟原木时钟创意现代简约实木北欧客厅卧室钟表',
    image:
      'http://demo26.crmeb.net/uploads/attach/2019/05/23/fd79a0af5d4a3eda1572cae99f6725c5.jpg',
    ficti: 10,
    price: 1499,
    classify: '卫浴清洁',
    stock: 30,
    sales: 10,
    status: false,
    unit_name: '件',
    keywords: ''
  }
		]
	}
}
   

通过情况,tableData都是通过调用https接口获取的数据列表。

总的来说,二次封装的大致思路如下:

  • 1、拷贝element-ui源码到我们自己的文档(不熟悉时,我们可以手写便于熟悉element-ui)
  • 2、抽取出需要父类传参的数据,定义props接收
  • 3、通过v-for指令进行循环和绑定数据
  • 4、通过v-if指令对需要不同类型渲染的数据进行不同的处理
  • 5、在父组件中引入我们二次封装的子组件,并传参。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值