vue3 ts 简单动态表单 和表格

ts 复制代码
<template>
  <div style="padding: 15px">
    <el-card>
      <el-form :inline="true" ref="formRef" :model="dynamicForm">
        <el-form-item
          v-for="(column, index) in dynamicForm.columns"
          :key="column.field + '.' + index"
          :label="column.label"
          :prop="column.prop"
        >
          <el-input v-model="column.value" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm(formRef)"> 查询 </el-button>
          <el-button @click="resetForm(formRef)">重置</el-button>
        </el-form-item>
      </el-form>
      <div class="table">
        <el-button type="primary" size="small" @click="handleRefresh">刷新</el-button>
        <el-button type="success" size="small" @click="handleSave">添加</el-button>
        <el-button type="warning" size="small" @click="handleUpdate">编辑</el-button>
        <el-button type="danger" size="small" @click="handleRemove">删除</el-button>
        <el-button type="info" size="small" @click="handleExport">导出</el-button>
        <el-table
          ref="tableRef"
          :data="tableData"
          stripe
          style="width: 100%"
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" :selectable="selectable" width="55" />

          <el-table-column
            v-for="column in tableColumn"
            :key="column.field"
            :prop="column.prop"
            :label="column.label"
            :width="column.width"
          />

          <el-table-column fixed="right" label="操作" min-width="120">
            <template #default="scope">
              <el-button type="primary" size="small" @click="handleDetail(scope.$index, scope.row)"
                >查看</el-button
              >
              <el-button size="small" @click="handleEdit(scope.$index, scope.row)">
                编辑
              </el-button>
              <el-button type="danger" size="small" @click="handleDelete(scope.$index, scope.row)">
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div class="page">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="pageSizes"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>
  </div>
</template>
<style lang="css">
.page {
  padding: 15px;
}
</style>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import type { FormInstance, TableInstance } from 'element-plus'

interface FormColumn {
  field: string
  label: string
  prop: string
  width: string
  value: string
}

interface TableColumn {
  field: string
  label: string
  prop: string
  width: string
}

const formRef = ref<FormInstance>()
const dynamicForm = reactive<{
  columns: FormColumn[]
}>({
  columns: [
    {
      prop: 'date',
      label: 'date',
      field: 'date',
      width: 'auto',
      value: '',
    },
    {
      prop: 'name',
      label: 'name',
      field: 'name',
      width: 'auto',
      value: '',
    },
    {
      prop: 'address',
      label: 'address',
      field: 'address',
      width: 'auto',
      value: '',
    },
  ],
})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
      console.log(dynamicForm)
    } else {
      console.log('error submit!', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  dynamicForm.columns?.forEach((column) => {
    column.value = ''
  })
  formEl.resetFields()
}

const tableRef = ref<TableInstance>()

const selection = ref<object[]>([])

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const selectable = (row: object) => []

const handleSelectionChange = (val: object[]) => {
  selection.value = val
}

const tableColumn: TableColumn[] = [
  {
    prop: 'date',
    label: 'date',
    field: 'date',
    width: 'auto',
  },
  {
    prop: 'name',
    label: 'name',
    field: 'name',
    width: 'auto',
  },
  {
    prop: 'address',
    label: 'address',
    field: 'address',
    width: 'auto',
  },
]
const tableData = [
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
]

const handleRefresh = () => {}

const handleSave = () => {}

const handleUpdate = () => {
  if (selection.value.length !== 1) {
    console.log(selection.value)
  }
}

const handleRemove = () => {
  if (selection.value.length === 0) {
    console.log(selection.value)
  }
}

const handleExport = () => {
  if (selection.value.length === 0) {
    console.log(selection.value)
  }
}

const handleDetail = (index: number, row: object) => {
  console.log(index, row)
}
const handleEdit = (index: number, row: object) => {
  console.log(index, row)
}
const handleDelete = (index: number, row: object) => {
  console.log(index, row)
}

const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = ref([10, 50, 100])
const total = ref(1000)

const handleSizeChange = (val: number) => {
  console.log(`${val} items per page`)
}
const handleCurrentChange = (val: number) => {
  console.log(`current page: ${val}`)
}
</script>
相关推荐
HarvestHarvest1 分钟前
【Copy Web独立开发者实战:我是如何用 AI 实现网页 UI 1:1 完美复刻的?】
前端·人工智能·ui
RuoyiOffice2 分钟前
从 0 到 1 搭建 RuoyiOffice:30 分钟跑通后端+前端+移动端
前端·spring boot·uni-app·开源·oa·ruoyioffice·hrm
昭昭颂桉a4 分钟前
TypeScript 前端的必修课,从 JS 到 TS
开发语言·前端·javascript·typescript
用户938515635074 分钟前
从零实现一个 Todos 应用:原生 Ajax + Node 服务,顺便吃透 JSON.stringify
前端·javascript·后端
英勇无比的消炎药5 分钟前
少踩坑TinyVue插槽事件编码规范详解
vue.js
程序猿阿伟7 分钟前
《Chrome扩展:穿透沙箱与签名体系的技术本质》
前端·chrome
飘尘8 分钟前
豆包里一句话就能P图生视频,背后究竟发生了什么?
前端·人工智能·aigc
codeking13 分钟前
3 步把 AI 桌面自动化从失控拉回可用
javascript·架构
神明不懂浪漫19 分钟前
【第三章】CSS(一)——基础选择器、CSS的属性
前端·css·html·css3
IVEN_28 分钟前
本地正常,Docker 怎么就空白:Next.js SSR 的 Alpine musl DNS 陷阱
前端·docker·next.js