vue3中基于element-plus封装一个表格弹框组件,要求可以单选和多选table数据

单选:
在这里插入图片描述

<template>
  <SelectMaterial
      ref="selectMaterialRef"
      check="checkbox"
      @select="selectMaterial"
    ></SelectMaterial>
   <el-button type="primary" size="small" icon="el-icon-plus" @click="handleAddMaterial"
     >添加备件</el-button>
</template>
<script setup>
import { ref } from 'vue';

const selectMaterialRef = ref('');
// 选择事件
const selectMaterial = data => {
  console.log('选择的表格数据', data);
};
// 打开添加备件弹框
const handleAddMaterial = () => {
  selectMaterialRef.value.openDialog();
};
</script>

在这里插入图片描述

多选:
在这里插入图片描述

<template>
  <SelectMaterial
      ref="selectMaterialRef"
      check="checkbox"
      @select="selectMaterial"
    ></SelectMaterial>
   <el-button type="primary" size="small" icon="el-icon-plus" @click="handleAddMaterial"
     >添加备件</el-button>
</template>
<script setup>
import { ref } from 'vue';

const selectMaterialRef = ref('');
// 选择事件
const selectMaterial = data => {
  console.log('选择的表格数据', data);
};
// 打开添加备件弹框
const handleAddMaterial = () => {
  selectMaterialRef.value.openDialog();
};
</script>

在这里插入图片描述

弹框表格组件代码

<template>
  <el-dialog v-model="dialogShow" @close="handleClose" width="50%" title="选择备件">
    <el-table
      border
      ref="tableRef"
      :data="tableData"
      :row-key="row => row.id"
      :header-cell-style="{ textAlign: 'center', backgroundColor: '#f3f3f3' }"
      :cell-style="{ textAlign: 'center' }"
      @selection-change="handleSelectionChange"
      style="height: 352px; overflow: auto; margin: 10px 0"
      size="small"
    >
      <el-table-column v-if="check === 'checkbox'" type="selection"></el-table-column>
      <el-table-column v-else-if="check === 'radio'" width="50">
        <template #default="scope">
          <el-radio v-model="selectedRow" :value="scope.row.id"></el-radio>
        </template>
      </el-table-column>
      <el-table-column type="index" width="80" label="序号">
        <template #default="{ $index }">
          {{ (currentPage - 1) * pageSize + $index + 1 }}
        </template>
      </el-table-column>
      <el-table-column prop="partNumber" label="备件编号"></el-table-column>
      <el-table-column prop="partName" label="备件名称"></el-table-column>
      <el-table-column prop="specification" label="规格型号"></el-table-column>
      <el-table-column prop="manufacturer" label="生产厂家"></el-table-column>
      <el-table-column prop="unit" label="单位"></el-table-column>
    </el-table>
    <div style="display: flex; justify-content: flex-end; margin-top: 10px">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[10, 20, 30, 40]"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        small
      >
      </el-pagination>
    </div>
    <div style="text-align: center; margin-top: 20px">
      <el-button size="small" @click="handleClose" style="margin-right: 30px;">取消</el-button>
      <el-button size="small" type="primary" @click="handleSelect">选择</el-button>
    </div>
  </el-dialog>
</template>

<script name="select-material-dialog" setup>
import { ref } from 'vue';

// 对话框是否可见
const dialogShow = ref(false);
// 多选选中的行
const selectedRows = ref([]);
// 单选选中的行
const selectedRow = ref(null);
// 当前页码
const currentPage = ref(1);
// 每页显示的条数
const pageSize = ref(10);
// 总条数
const total = ref(0);
// 表格数据
const tableData = ref([]);
// 表格ref
const tableRef = ref(null);

// 定义属性
const props = defineProps({
  // 选择模式,可以是 'radio' 或 'checkbox'
  check: {
    type: String,
    default: 'checkbox',
  },
});

// 定义事件
const $emit = defineEmits(['select']);

// 获取数据的方法
const fetchData = async () => {
  // 模拟接口请求,这里使用 setTimeout 来模拟异步操作
  await new Promise(resolve => setTimeout(resolve, 1000));

  // 更新数据
  const data = Array.from({ length: pageSize.value }, (_, i) => ({
    id: (currentPage.value - 1) * pageSize.value + i + 1, // 注意这里的 +1,因为 id 应该从 1 开始,而不是从 0 开始
    partNumber: `编号${(currentPage.value - 1) * pageSize.value + i + 1}`, // 同样,编号也应该从 1 开始
    partName: `名称${i}`,
    specification: `规格${i}`,
    manufacturer: `厂家${i}`,
    unit: `单位${i}`,
  }));
  tableData.value = data;
  total.value = 100; // 假设总条数为 100
};

// 切换对话框的可见状态
const openDialog = () => {
  dialogShow.value = true;
};

// 关闭对话框
const handleClose = () => {
  dialogShow.value = false;
};

// 处理分页器当前页改变
const handleCurrentChange = async val => {
  console.log('current', val);
  currentPage.value = val;
  await fetchData();
};

// 处理选项变化
const handleSelectionChange = val => {
  selectedRows.value = val;
};

// 处理每页显示的条数改变
const handleSizeChange = async val => {
  pageSize.value = val;
  await fetchData();
};

// 处理选择按钮点击
const handleSelect = () => {
  if (props.check === 'radio') {
    const selectedData = tableData.value.find(row => row.id === selectedRow.value);
    $emit('select', selectedData);
  } else {
    $emit('select', selectedRows.value);
  }
  handleClose();
};

// 暴露方法和属性
defineExpose({ openDialog });
// 初始获取数据
fetchData();
</script>

这里多啰嗦一句单选,我这里是自定义列,使用单选框的方式实现的

<el-table-column v-else-if="check === 'radio'" width="50">
  <template #default="scope">
    <el-radio v-model="selectedRow" :label="scope.row.id"></el-radio>
  </template>
</el-table-column>
<script>
// 选中的行的数据
const selectedRow = ref(null);
// 处理选择按钮点击
const handleSelect = () => {
  if (props.check === 'radio') {
    const selectedData = tableData.value.find(row => row.id === selectedRow.value);
    $emit('select', selectedData);
  } 
};
</script>

为什么要这样呢,因为我开始是使用多选加反选的方式实现单选,但这样存在一个bug,就是多选框的表头有个全选按钮,点击那个全选的时候会出现反选的问题。

<template>
    <el-table
      ref="tableRef"
      :data="tableData"
      @selection-change="handleSelectionChange"
    >
      <el-table-column  type="selection"></el-table-column>
      ......
    </el-table>
</template>
<script>
const selectedRow = ref(null);
const handleSelectionChange = (val: []) => {
  console.log(val);
  if (val.length > 1) {
  	// 单选
    tableRef.value!.toggleRowSelection(val[0], val[val.length - 1]);
    selectedRow .value = [val[val.length - 1]];
  } else {
    // 多选
    selectedRow .value = val;
  }
}
</script>
  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,下面给出一个简单的优惠券组件示例,使用 Vue 3 和 Element Plus。 首先需要安装 Element Plus: ``` npm i element-plus ``` 然后在项目引入: ```javascript import { createApp } from 'vue'; import ElementPlus from 'element-plus'; import 'element-plus/lib/theme-chalk/index.css'; import App from './App.vue'; createApp(App).use(ElementPlus).mount('#app'); ``` 接下来就可以创建一个 Coupon 组件: ```vue <template> <el-card class="coupon-card"> <div class="coupon-header"> <span class="coupon-title">{{ title }}</span> <span class="coupon-amount">{{ amount }}</span> </div> <div class="coupon-content"> <div class="coupon-code">{{ code }}</div> <div class="coupon-validity">{{ validity }}</div> </div> </el-card> </template> <script> export default { name: 'Coupon', props: { title: { type: String, required: true }, amount: { type: String, required: true }, code: { type: String, required: true }, validity: { type: String, required: true } } } </script> <style scoped> .coupon-card { width: 300px; padding: 20px; } .coupon-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .coupon-title { font-size: 20px; font-weight: bold; } .coupon-amount { font-size: 24px; font-weight: bold; } .coupon-code { margin-bottom: 10px; font-size: 18px; } .coupon-validity { font-size: 14px; } </style> ``` 在父组件使用: ```vue <template> <div class="coupons"> <Coupon title="优惠券1" amount="50元" code="ABC123" validity="2021-12-31" /> <Coupon title="优惠券2" amount="30元" code="DEF456" validity="2021-12-31" /> </div> </template> <script> import Coupon from './components/Coupon.vue'; export default { name: 'Coupons', components: { Coupon } } </script> <style> .coupons { display: flex; justify-content: space-around; } </style> ``` 这样就可以在页面上展示优惠券组件了。当然,这只是一个简单的示例,你可以根据实际需求对组件进行更多的定制和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jieyucx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值