当前位置: 首页 > news >正文

el-table 结合 slot 具名插槽遍历封装列表模板

基础效果

在这里插入图片描述

  • 要实现以上效果,可对 el-table 进行封装,将列配置视为数组,循环 el-table-column 标签
  • 模板组件
<div class="tableSlot">
   <el-table :data="dataList" border>
    <el-table-column
      v-for="(item, index) in columns"
      :key="index"
      :prop="item.prop"
      :label="item.label"
      :width="item.width"
    ></el-table-column>
  </el-table>
</div>
<script>
export default {
  props: {
    // 表格数据
    dataList: {
      type: Array,
      default: () => [],
    },
    // 列配置
    columns: {
      type: Array,
      default: () => [],
    },
  },
  name: "tableSlot",
};
</script>
  • 父组件
<div class="dataList">
  <p>表格 - 嵌套渲染</p>
  <tableSlot :dataList="dataList" :columns="columns"></tableSlot>
</div>
<script>
import tableSlot from "../../common/tableSlot.vue";
import axios from "axios";
export default {
  name: "dataList",
  components: { tableSlot },
  data() {
    return {
      dataList: [],
      // prop 为数据的 key,label 为表头
      columns: [
        { prop: "id", label: "用户ID" },
        { prop: "date", label: "日期" },
        { prop: "name", label: "姓名" },
        { prop: "count", label: "金额" },
        { prop: "address", label: "地址", width: "400" },
      ],
    };
  },
  mounted() {
    this.getData1();
  },
  methods: {
    getData1() {
      this.dataList = [];
      axios.get("/list2").then((res) => {
        console.log("res", res);
        if (res.status == 200) {
          this.dataList = res.data;
        }
      });
    },
  },
};
</script>

添加特殊样式

  • 如果想为某些列添加特殊样式,可以在 columns 中添加特殊参数
  • 比如为金额列添加颜色,大于 0 的显示绿色,否则显示红色
  • 比如添加操作列并回传点击事件

在这里插入图片描述

  • 模板组件
<el-table :data="dataList" border>
  <el-table-column
    v-for="(item, index) in columns"
    :key="index"
    :prop="item.prop"
    :label="item.label"
    :width="item.width"
  >
    <template slot-scope="scope">
      <template v-if="item.reset">
        <!-- 特殊样式 - 数值颜色 -->
        <template v-if="item.reset == 'countColor'">
          <div :class="scope.row[item.prop] > 0 ? 'green' : 'red'">
            {{
              scope.row[item.prop] > 0
                ? "+" + scope.row[item.prop]
                : scope.row[item.prop]
            }}
          </div>
        </template>
        <!-- 特殊样式 - 操作按钮组 -->
        <template v-if="item.reset == 'operate'">
          <el-button
            type="text"
            v-for="(itemBtn, indexBtn) in item.btns"
            :key="indexBtn"
            @click="handelRow(itemBtn, scope.row)"
          >
            {{ itemBtn }}
          </el-button>
        </template>
      </template>
      <template v-else>
        <!-- 非特殊样式,直接展示 -->
        {{ scope.row[item.prop] }}
      </template>
    </template>
  </el-table-column>
</el-table>
<script>
export default {
  props: {
    // 表格数据
    dataList: {
      type: Array,
      default: () => [],
    },
    // 列配置
    columns: {
      type: Array,
      default: () => [],
    },
  },
  name: "tableSlot",
  methods: {
    handelRow(type, row) {
      console.log("点击了当前行", type, row);
      this.$emit("handelRow", type, row);
    },
  },
};
</script>
<style lang="less" scoped>
.tableSlot {
  .red {
    color: red;
  }
  .green {
    color: green;
  }
}
</style>
  • 父组件
<div class="dataList">
  <p>表格 - 嵌套渲染</p>
  <tableSlot :dataList="dataList" :columns="columns" @handelRow="handelRow"></tableSlot>
</div>
<script>
import tableSlot from "../../common/tableSlot.vue";
import axios from "axios";
export default {
  name: "dataList",
  components: { tableSlot },
  data() {
    return {
      dataList: [],
      // 用 reset 来标记特殊列的展示样式
      columns: [
        { prop: "id", label: "用户ID" },
        { prop: "date", label: "日期" },
        { prop: "name", label: "姓名" },
        { prop: "count", label: "金额", reset: "countColor" }, // reset 标记,特殊颜色
        { prop: "address", label: "地址", width: "400" },
        {
          prop: "operate",
          label: "操作",
          width: "200",
          reset: "operate",
          btns: ["按钮1", "按钮2"],
        }, // reset 标记,按钮组
      ],
    };
  },
  mounted() {
    this.getData1();
  },
  methods: {
    getData1() {
      this.dataList = [];
      axios.get("/list2").then((res) => {
        console.log("res", res);
        if (res.status == 200) {
          this.dataList = res.data;
        }
      });
    },
    handelRow(type, row) {
      console.log("从表格模板传过来的点击事件", type, row);
    },
  },
};
</script>
  • 点击表格第一行的按钮1时,可以看到,父组件可以接收到传递的参数
    在这里插入图片描述

利用具名插槽

  • 如果 reset 标记不够满足父组件中的定制化样式,还可以利用具名插槽
  • 比如为姓名列添加文本内容
  • 比如截取日期格式

在这里插入图片描述

  • 可以将 columns 数组中的 prop 属性作为具名插槽的 name 来使用

  • 模板组件

<template>
  <div class="tableSlot">
    <el-table :data="dataList" border>
      <el-table-column
        v-for="(item, index) in columns"
        :key="index"
        :prop="item.prop"
        :label="item.label"
        :width="item.width"
      >
        <template slot-scope="scope">
          <template v-if="item.reset">
            <!-- 特殊样式 - 数值颜色 -->
            <template v-if="item.reset == 'countColor'">
              <div :class="scope.row[item.prop] > 0 ? 'green' : 'red'">
                {{
                  scope.row[item.prop] > 0
                    ? "+" + scope.row[item.prop]
                    : scope.row[item.prop]
                }}
              </div>
            </template>
            <!-- 特殊样式 - 操作按钮组 -->
            <template v-if="item.reset == 'operate'">
              <el-button
                type="text"
                v-for="(itemBtn, indexBtn) in item.btns"
                :key="indexBtn"
                @click="handelRow(itemBtn, scope.row)"
              >
                {{ itemBtn }}
              </el-button>
            </template>
            <!-- 特殊样式 - 具名插槽,去父组件展示,回传 row 的内容 -->
            <template v-if="item.reset == 'slot'">
              <!-- 将 prop 属性作为具名插槽的 name 来保证唯一 -->
              <slot :name="item.prop" :item="scope.row"></slot>
            </template>
          </template>
          <template v-else>
            <!-- 非特殊样式,直接展示 -->
            {{ scope.row[item.prop] }}
          </template>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  props: {
    // 表格数据
    dataList: {
      type: Array,
      default: () => [],
    },
    // 列配置
    columns: {
      type: Array,
      default: () => [],
    },
  },
  name: "tableSlot",
  methods: {
    handelRow(type, row) {
      console.log("点击了当前行", type, row);
      this.$emit("handelRow", type, row);
    },
  },
};
</script>
<style lang="less" scoped>
.tableSlot {
  .red {
    color: red;
  }
  .green {
    color: green;
  }
}
</style>
  • 父组件
<template>
  <div class="dataList">
    <p>表格 - 嵌套渲染</p>
    <tableSlot :dataList="dataList" :columns="columns" @handelRow="handelRow">
      <!-- 姓名的插槽,接收 item 值,渲染格式 【姓名】 -->
      <template v-slot:name="{ item }">{{ `【${item.name}】` }}</template>
      <!-- 日期的插槽,接收 item 值,渲染格式 截取掉时间中的时分秒,只保留年月日 -->
      <template v-slot:date="{ item }">{{ item.date.split(" ")[0] }}</template>
    </tableSlot>
  </div>
</template>
<script>
import tableSlot from "../../common/tableSlot.vue";
import axios from "axios";
export default {
  name: "dataList",
  components: { tableSlot },
  data() {
    return {
      dataList: [],
      columns: [
        { prop: "id", label: "用户ID" },
        { prop: "date", label: "日期", reset: "slot" }, // reset 标记,插槽
        { prop: "name", label: "姓名", reset: "slot" }, // reset 标记,插槽
        { prop: "count", label: "金额", reset: "countColor" },
        { prop: "address", label: "地址", width: "400" },
        {
          prop: "operate",
          label: "操作",
          width: "200",
          reset: "operate",
          btns: ["按钮1", "按钮2"],
        },
      ],
    };
  },
  mounted() {
    this.getData1();
  },
  methods: {
    getData1() {
      this.dataList = [];
      axios.get("/list2").then((res) => {
        console.log("res", res);
        if (res.status == 200) {
          this.dataList = res.data;
        }
      });
    },
    handelRow(type, row) {
      console.log("从表格模板传过来的点击事件", type, row);
    },
  },
};
</script>

相关文章:

  • jenkins自动发版vue前端笔记
  • JSON格式,C语言自己实现,以及直接调用库函数(一)
  • HTTP、HTTPS区别可靠性及POST为什么比GET安全的探讨
  • 结构风荷载理论与Matlab计算
  • Linux后台启动命令nohup并且MobaXterm后台启动断网也不关闭软件
  • 《探秘DeepSeek优化器:解锁模型训练的高效密码》
  • nodejs及搭建
  • 零基础用AI—AI伦理风险防控的十大核心策略与全球协同治理实践
  • 文章学习---经颅聚焦超声刺激(TUS)对灵长类动物大脑皮层激活的影响
  • SOME/IP--协议英文原文讲解6
  • Centos7 使用 yum 报错 Could not retrieve mirrorlist
  • Nmap:网络扫描与安全评估的多功能工具
  • leetcode4:寻找两个正序数组的中位数
  • 双非一本电子信息专业自学嵌入式,学完 Linux 后咋走?单片机 FreeRTOS 要补吗?
  • Elasticsearch7.6.2 安装过程
  • 论文笔记:How Much Can Time-related Features Enhance Time Series Forecasting?
  • python-leetcode 35.二叉树的中序遍历
  • 代码随想录算法训练营Day51
  • 【Go语言快速上手】第二部分:Go语言进阶之并发编程
  • 新手向:SpringBoot后端查询到数据,前端404?(附联调时各传参方式注解总结-带你一文搞定联调参数)
  • 多地景区发公告称售票达接待峰值,有景区暂停网络和线下售票
  • 高速变道致连环车祸,白车“骑”隔离栏压住另一车,交警回应
  • 侧记|“五五购物节”启动!最大力度补贴,买买买 “666”
  • A股三大股指涨跌互现:3343股收涨,两市成交超1.1万亿元
  • 巴西外长维埃拉:国际形势日益复杂,金砖国家必须发挥核心作用
  • 浙江官宣:五一假期,没电、没气、没油车辆全部免费拖离高速