自学内容网 自学内容网

【ElementPlus】在Vue3中实现表格组件封装

预览

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/2a954e6b844947f8a7a3e7f30d39421e.pn

搜索筛选组件

<template>
  <div>
    <el-form
      ref="formView"
      :model="formData"
      label-width="auto"
      label-position="right"
      :label-col-style="{ 'min-width': '100px' }"
      :inline="true"
    >
      <el-form-item :prop="column.prop" :label="column.label" v-for="column in columns" :key="column.prop">
        <slot :name="column.prop" :query="formData">
          <el-input v-model="formData[column.prop]" :placeholder="`请输入${column.label}`" clearable />
        </slot>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="onSubmit">查询</el-button>
        <el-button icon="Refresh" @click="onReset">重置</el-button>
      </el-form-item>
      <div class="mb15">
        <slot name="handleMenu" />
      </div>
    </el-form>
  </div>
</template>
<script setup>
import { ref, toRaw, watch, onMounted } from "vue"

const props = defineProps(["columns"])
const emit = defineEmits(["change", "submit", "reset"])
const formView = ref(null)
let formData = ref()
let isReset = false
watch(
  () => formData,
  (data) => {
    if (isReset) {
      isReset = false
      return
    }
    emit("change", toRaw(data.value))
  },
  { deep: true, immediate: true }
)

onMounted(() => {
  formData.value = columnsToFormData()
})
function onSubmit() {
  emit("submit", toRaw(formData.value))
}

function onReset() {
  isReset = true
  formData.value = columnsToFormData()
  emit("reset", toRaw(formData.value))
}

function columnsToFormData() {
  return Object.fromEntries(
    [].concat(
      ...props.columns.map((item) => {
        if (item.items) {
          return item.items.map((iItem) => [iItem.prop, item?.defaultValue || null])
        }
        return [[item.prop, item?.defaultValue || null]]
      })
    )
  )
}
</script>

表格组件

<template>
  <div>
    <!-- 筛选条件相关 -->
    <query-header :columns="queryColumns" @change="onQueryParamsChange" @submit="onSubmit" @reset="onReset">
      <template v-for="item in queryColumns" :key="item.prop" v-slot:[item.prop]="{ query }">
        <slot :name="`${item.prop}Query`" :query="query" />
      </template>
      <template #handleMenu>
        <slot name="handleMenu" />
      </template>
    </query-header>
    <!-- 表格 -->
    <el-table ref="tableView" :data="list" :loading="loading" @selection-change="onSelectionChange">
      <!-- 表格选择 -->
      <el-table-column type="selection" width="55" v-if="props.selection" />
      <!-- 展开行内容 -->
      <el-table-column type="expand" v-if="expand">
        <template #default="{ row }">
          <slot name="expand" :row="row" />
        </template>
      </el-table-column>
      <!-- 表格列 -->
      <el-table-column
        v-for="column in tableColumnsList"
        :key="column.prop"
        :align="column.align ? column.align : 'center'"
        :label="column.label"
        :prop="column.prop"
        :width="column.width"
        :sortable="column.sortable"
        show-overflow-tooltip
      >
        <template #default="scope">
          <slot :name="column.prop" :row="scope.row">
            {{ scope.row[column.prop] }}
          </slot>
        </template>
      </el-table-column>
      <!-- 操作菜单 -->
      <slot name="tableMenu" />
    </el-table>
  </div>
  <!-- 分页 -->
  <el-pagination
    v-model:current-page="queryForm.page_no"
    v-model:page-size="queryForm.page_size"
    :page-sizes="[1, 10, 20, 50, 100]"
    background
    :background="background"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
    @size-change="onPageSizeChange"
    @current-change="onPageChange"
    class="mt20 flex"
    style="justify-content: flex-end"
  />
</template>
<script setup>
import request from "@/utils/request"
import QueryHeader from "./QueryHeader.vue"
import { ref, reactive, onMounted, watch } from "vue"

/* 父组件传递参数
    apiUrl: { type: String, required: true },   // 请求地址
    tableColumns: { type: Array, required: true }, // 表格列
    selection: { type: Boolean, default: false }, // 是否可多选
    rowKey: { type: String, default: '' }, // 行数据的 Key,用来优化 Table 的渲染;
    expand: { type: Boolean, default: false }, // 是否可展开
 */
const props = defineProps(["apiUrl", "tableColumns", "expandable", "selection", "rowKey", "expand"])

const tableView = ref(null)
const queryColumns = ref([])
const tableColumnsList = ref([])

watch(
  () => props.tableColumns,
  (newVal, oldVal) => {
    queryColumns.value = newVal.filter((item) => {
      return item.search
    })
    tableColumnsList.value = newVal.filter((item) => {
      return !item.hide
    })
  }
)

onMounted(() => {
  queryColumns.value = props.tableColumns.filter((item) => {
    return item.search
  })
  tableColumnsList.value = props.tableColumns.filter((item) => {
    return !item.hide
  })
  getList()
})

/* 获取列表数据 */
const loading = ref(false)
const total = ref(0)
const list = ref([])
const queryForm = reactive({
  page_no: 1,
  page_size: 10,
})
function getList() {
  loading.value = true
  let params = JSON.parse(JSON.stringify(queryForm))
  request
    .get({
      url: props.apiUrl,
      params,
    })
    .then((res) => {
      list.value = res.lists
      total.value = res.count
      loading.value = false
    })
}
/*  */
/* 表格分页页数切换 */
function onPageChange(num) {
  queryForm.page_no = num
  getList()
}
/* 表格每页数量切换 */
function onPageSizeChange(num) {
  queryForm.page_size = num
  queryForm.page_no = 1
  getList()
}

/* 重置查询 */
function queryList(dataList) {
  /* dataList除query-header 外查询参数 */
  if (dataList && dataList.length > 0) {
    for (let item of dataList) {
      queryForm[item.key] = item.value
    }
  }
  queryForm.page_no = 1
  getList()
}
/* 表格选择 */
const emit = defineEmits(["select"])
function onSelectionChange(value) {
  emit("select", value)
}
/* 查询条件-点击查询按钮 */
function onSubmit() {
  queryList()
}
/* 查询条件-参数变化 */
function onQueryParamsChange(value) {
  Object.assign(queryForm, value)
}
/*  查询条件-清空参数 */
function onReset(value) {
  Object.assign(queryForm, value)
  queryList()
}
/* 暴露到父组件方法 */
defineExpose({
  queryList,
})
</script>

页面引用

<template>
  <div class="app-container home">
    <query-table ref="tableViewRef" apiUrl="/adviser/lists" :table-columns="tableColumns" :selection="true">
      <!-- 筛选条件自定义 -->
      <template #create_timeQuery="{ query }">
        <el-date-picker
          v-model="query.create_time"
          type="daterange"
          value-format="YYYY-MM-DD"
          range-separator="-"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          @change="onTimeChange"
        />
      </template>
      <template #is_disableQuery="{ query }">
        <el-select v-model="query.is_disable" clearable>
          <el-option label="是" :value="1"></el-option>
          <el-option label="否" :value="0"></el-option>
        </el-select>
      </template>
      <template #handleMenu>
        <el-row>
          <el-col :span="12">
            <el-space>
              <el-button type="primary" icon="Plus" @click="clickAdd('')" v-perms="['adviser/add']">添加</el-button>
              <el-button>批量导入</el-button>
              <el-button>批量导出</el-button>
            </el-space>
          </el-col>
        </el-row>
      </template>
      <!-- table自定义列 -->
      <template #is_disable="{ row }">
        <el-switch v-model="row.is_disable" :active-value="1" :inactive-value="0"></el-switch>
      </template>
      <template #tableMenu>
        <el-table-column label="操作" align="center" width="200">
          <template #default="{ row }">
            <router-link :to="`./info?id=${row.id}`">
              <el-button type="primary" link>详情</el-button>
            </router-link>
            <!-- <el-button v-perms="['adviser/edit']" type="primary" link @click="clickAdd(row.id)">
                            编辑
                        </el-button>
                        <el-button v-perms="['adviser/delete']" type="danger" link @click="handleDelete(row.id)">
                            删除
                        </el-button> -->
          </template>
        </el-table-column>
      </template>
    </query-table>
  </div>
</template>

<script setup name="Index">
import QueryTable from "@/components/QueryTable/index.vue"

const tableColumns = [
  { label: "顾问名称", prop: "name", search: true },
  { label: "手机号", prop: "mobile", search: true },
  { label: "微信号", prop: "user_id" },
  { label: "关联用户数", prop: "adviser_id", width: 150 },
  { label: "当前面试", prop: "commission", sortable: true },
  { label: "预约单", prop: "w_commission", sortable: true },
  { label: "服务单", prop: "wz_commission", sortable: true },
  { label: "创建时间", prop: "create_time", width: 160, search: true },
  { label: "是否启用", prop: "is_disable", search: true },
]
</script>

<style scoped lang="scss"></style>


原文地址:https://blog.csdn.net/qq_40476712/article/details/145278573

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!