vue3+ts,slot插槽,表格组件封装

新建三个文件

  • src\components\page-content\page-content.vue 表格公共文件

  • src\view\main\system\department\config\content.config.ts表格数据配置

  • src\view\main\system\department\department.vue 父组件,传输数据

  1. department.vue

<template>
  <div class="department">
    <div class="user">
      <div class="content">
        <page-content ref="contentRef" @addClickBtn="handleAddClick" @editClickBtn="handleEditClick"  :contentConfig="contentConfig">
          <template #leader="scope">
            <!-- 接受插槽传输过来的scoped数据,获取插槽数据, -->
            <div class="slot">{{ scope.row[scope.prop] }}</div>
          </template>
          <template #parentId="scope">
            <!-- 接受插槽传输过来的scoped数据,对scoped数据进行处理 -->
            <div class="slot">{{ scope.row[scope.prop] }}</div>
          </template>
        </page-content>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import pageContent from '@/components/page-content/page-content.vue'
import contentConfig from './config/content.config'
</script>

<style lang="scss" scoped>
.department {}

.slot {
  color: red
}
</style>
 
  1. page-content.vue

条件渲染column数据(timer、handler、custom)

slot插槽对column数据进行处理和样式修改

编辑、删除方法的网络请求

<template>
  <div class="user-content">
    <!-- 头部header -->
    <div class="header">
      <h3>{{ contentConfig.header?.title ?? '数据列表' }}</h3>
      <el-button type="primary" @click="addPage">{{ contentConfig.header?.btnTitle ?? '添加数据' }}</el-button>
    </div>
    <!-- 中间表格 table-->
    <div class="table">
      <el-table :data="pageList" border style="width: 100%" ref="pageListRef">
        <!-- 可以用v-bind来绑定,等同于上面的数据 -->
        <template v-for="item in contentConfig.tableColumn" :key="item.prop">
          <!-- 当表格数据为时间数据时,处理数据-->
          <template v-if="item.type === 'timer'">
            <el-table-column v-bind="item">
              <template #default="scoped">
                {{ formatUTC(scoped.row[item.prop]) }}
              </template>
            </el-table-column>
          </template>
          <!-- 当表格为按钮时 -->
          <template v-else-if="item.type === 'handler'">
            <el-table-column :label="item.label" width="200">
              <template #default="scoped">
                <el-button icon="Edit" @click="editClickBtn(scoped.row)">编辑</el-button>
                <el-button icon="Delete" @click="deleteClickBtn(scoped.row.id)">删除</el-button>
              </template>
            </el-table-column>
          </template>
          <!-- 插槽 -->
          <template v-else-if="item.type === 'custom'">
            <el-table-column :label="item.label">
              <template #default="scope">
                <!-- 将数据绑定在scope上,把scope数据传输给父组件,给scope数据添加prop属性-->
                <slot :name="item.slotName" v-bind="scope" :prop="item.prop"></slot>
              </template>
            </el-table-column>
          </template>
          <!-- 表格数据为普通数据时 -->
          <template v-else>
            <el-table-column v-bind="item" />
          </template>
        </template>
      </el-table>
    </div>
    <!-- 分页-pagination -->
    <div class="pagination">
      <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20]"
        :small="small" :disabled="disabled" :background="background" layout="total, sizes, prev, pager, next, jumper"
        :total="totalPageCount" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { formatUTC } from '@/utils/format'
import userSystemStore from '@/store/main/system/system'
import userMainStore from '@/store/main/main'
import { storeToRefs } from 'pinia'
interface IContent {
  contentConfig: {
    header?: {
      title?: string
      btnTitle?: string
    }
    tableColumn: any[]
    width?: {
      type: number
      default: 120
    }
    pageName: string
  }
}

const prop = defineProps<IContent>()
console.log('contentConfig.tableColumn :>> ', prop)
const userSystem = userSystemStore()
const userMain = userMainStore()
//由于这个方法是异步的,所以拿不到userSystem里的数据,可以用computed方法和storeToRefs方法
// userSystem.postpageListAction()
const { pageList } = storeToRefs(userSystem)
const { totalPageCount } = storeToRefs(userSystem)
// 编辑用户
function editClickBtn(item: any) {
  console.log('item0000000 :>> ', item)
  emit('editClickBtn', item)
}
//删除用户
function deleteClickBtn(id: number) {
  userSystem.deletePageAction(prop.contentConfig.pageName, id)
}
const emit = defineEmits(['addClickBtn', 'editClickBtn'])

//新建用户
function addPage() {
  emit('addClickBtn')
}
//==============================分页器==================================
const currentPage = ref(1)
const pageSize = ref(10)
const small = ref(false)
const background = ref(false)
const disabled = ref(false)
fetchpageListData()
//页码和每页数据条数改变时重新发送请求
function fetchpageListData(fetchpageListData: any = {}) {
  const size = pageSize.value
  const offset = (currentPage.value - 1) * size
  const info = { size, offset }
  //数据偏移量offset
  const queryInfo = { ...info, ...fetchpageListData }
  userSystem.postPageListAction(prop.contentConfig.pageName, queryInfo)
}
//将方法暴露给父组件
defineExpose({ fetchpageListData })
// 每页展示数据条数
const handleSizeChange = (val: number) => {
  pageSize.value = val
  fetchpageListData()
}
// 前往第几页和点击页数
const handleCurrentChange = (val: number) => {
  currentPage.value = val
  fetchpageListData()
}
</script>

<style lang="scss" scoped>
.user-content {
  background-color: #fff;
}

.header {
  margin-top: 20px;

  padding: 20px;
  display: flex;
  justify-content: space-between;
}

// 分页器
.pagination {
  display: flex;
  justify-content: right;
  padding: 10px;
}
</style>
  1. content.config.ts

// 配置department的serach区域的数据
const contentConfig = {
pageName: 'department',
  title: '部门列表',
  button: '新建部门',
  tableColumn: [
    {
      type: 'selection',
      width: '60px'
    },
    {
      type: 'index',
      label: '序号',
      width: '80px'
    },
    {
      label: '部门名称',
      prop: 'name',
      width: '120px'
    },
    {
      label: '部门领导',
      prop: 'leader'
    },
    {
      label: '上级部门',
      prop: 'parentId'
    },
    {
      type: 'timer',
      label: '创建时间',
      prop: 'createAt',
      width: '170px'
    },
    {
      type: 'timer',
      label: '更新时间',
      prop: 'updateAt',
      width: '170px'
    },
    {
      type: 'handler',
      label: '编辑'
      // prop: 'createAt'
    },
    {
      // 插槽数据
      type: 'custom',
      slotName: 'leader',
      label: '上级',
      prop: 'leader'
      // width: '150px'
    },
    {
      // 插槽数据
      type: 'custom',
      slotName: 'parentId',
      label: '级',
      prop: 'parentId'
      // width: '150px'
    }
  ]
}
export default contentConfig

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值