Crud 增删改查
z-crud
组件表单部分功能介绍。
如果您只想使用组件的筛选表单和表格功能,您需要查看以下示例。
基础用法
配置column
项的search
生成表单项。
label
和field
可以不传,默认取prop
和label
- 组件默认配置
clearable
、placeholder
和filterable
search
属性的具体配置可参考z-form
的column
项- 表单布局固定为
{ xs: 24, sm: 12, md: 8, lg: 8, xl: 6 }
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { result: { page: number, pageSize: number, list: RowData[], total: number } }
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
function mockApi(params: any): Promise<GetTableDataRes> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const params = {
...pagination.value,
...formData.value,
}
const res = await mockApi(params)
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
function handleSearch() {
pagination.value.page = 1
getTableData()
}
getTableData()
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
:columns="columns"
:options="options"
:loading="loading"
:action="false"
@refresh="getTableData"
@search="handleSearch"
@reset="handleSearch"
/>
</template>
配置search
的columns
字段也能达到相同的效果,如果你想配置表单labelWidth
等其他属性,也可以放入search
中
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
const searchFormConfig = ref({
labelWith: '80px',
columns: [
{
component: 'input',
label: '姓名',
field: 'name',
},
{
component: 'select',
label: '性别',
field: 'gender',
},
{
component: 'input',
label: '年龄',
field: 'age',
},
],
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:search="searchFormConfig"
:action="false"
:request="request"
/>
</template>
配置column
的form
也能生成查询表单项,但同时也会生成新增、编辑和查询表单项,如不需要,可配置add
和edit
字段为false
。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { result: { page: number, pageSize: number, list: RowData[], total: number } }
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'name',
label: '姓名',
add: false,
edit: false,
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
add: false,
edit: false,
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
add: false,
edit: false,
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
function mockApi(params: any): Promise<GetTableDataRes> {
console.log(params, 'any')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const params = {
...pagination.value,
...formData.value,
}
const res = await mockApi(params)
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
function handleSearch() {
pagination.value.page = 1
getTableData()
}
getTableData()
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
:columns="columns"
:options="options"
:loading="loading"
@refresh="getTableData"
@search="handleSearch"
@reset="handleSearch"
/>
</template>
如果某一个column
项不想要表格列,仅仅只想要表单项,在column
中不配置type
、slot
、render
、label
、prop
、component
等字段,再配置search
、form
等表单配置字段即可实现
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { result: { page: number, pageSize: number, list: RowData[], total: number } }
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref<RowData[]>([])
const columns = ref([
{
// 仅配置了search
search: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
function mockApi(params: any): Promise<GetTableDataRes> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const params = {
...pagination.value,
...formData.value,
}
const res = await mockApi(params)
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
function handleSearch() {
pagination.value.page = 1
getTableData()
}
getTableData()
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
:columns="columns"
:options="options"
:loading="loading"
:action="false"
@refresh="getTableData"
@search="handleSearch"
@reset="handleSearch"
/>
</template>
条件缓存
配置name
字段,会默认开启缓存,筛选表单数据和pagination
数据会缓存在sessionStorage
中,下次加载时会优先从缓存中获取条件数据。
数据获取需要在onMounted
生命周期中调用。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { result: { page: number, pageSize: number, list: RowData[], total: number } }
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
function mockApi(params: any): Promise<GetTableDataRes> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const params = {
...pagination.value,
...formData.value,
}
console.log(params, 'cache params')
const res = await mockApi(params)
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
function handleSearch() {
pagination.value.page = 1
getTableData()
}
onMounted(() => {
getTableData()
})
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
:columns="columns"
:options="options"
:loading="loading"
:action="false"
name="crudCache"
@refresh="getTableData"
@search="handleSearch"
@reset="handleSearch"
/>
</template>
配置request
后,缓存条件会在内部处理。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
time: [],
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
field: 'name',
label: '姓名',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'el-date-picker',
field: 'time',
label: '出生日期',
fieldProps: {
type: 'daterange',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
},
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi(params: any) {
console.log(params, 'cache params second')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:action="false"
:request="request"
name="nameCacheSecond"
/>
</template>
校验
form
字段中添加required
字段,或者formItemProps
中设置required
字段,即可设置必填,校验信息会根据label
自动生成也可自定义。z-crud
传入的search
对象配置rules
字段,可以定义表单校验规则。form
字段中表单项配置rules
,可以定义当前表单项校验规则。
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
time: [],
})
const tableData = ref([])
const searchFormConfig = ref({
labelWidth: '80px',
rules: {
time: [{ required: true, message: '出生日期必选' }],
},
})
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
field: 'name',
label: '姓名',
required: true,
message: '请将姓名填写完整',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
field: 'gender',
formItemProps: {
required: true,
label: '性别',
},
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'el-date-picker',
field: 'time',
label: '出生日期',
rules: {
required: true,
message: '出生日期必选',
},
fieldProps: {
type: 'daterange',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
},
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:action="false"
:search="searchFormConfig"
:request="request"
/>
</template>
表单项自定义
我们可以使用slot
或render
自定义表单项内容。
<script lang="ts" setup>
import { h, ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
age: '',
height: '身高自定义',
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
field: 'name',
label: '姓名',
},
},
{
prop: 'gender',
label: '性别',
search: {
slot: 'ageSlot',
label: '年龄',
},
},
{
prop: 'age',
label: '年龄',
search: {
render: () => h('span', {}, formData.value.height),
label: '身高',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:columns="columns"
:options="options"
:search="{ size: 'default' }"
:action="false"
:request="request"
>
<template #ageSlot>
<el-input v-model="formData.age" placeholder="请输入年龄" clearable />
</template>
</z-crud>
</template>
label、error自定义
label
和error
支持传入字符串、render
函数或拼接Slot的字符串
。
<script lang="ts" setup>
import { h, ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
time: [],
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
field: 'name',
label: () => h('span', {}, '姓名'),
required: true,
error: 'error message',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
field: 'gender',
label: 'labelSlot',
required: true,
error: h('span', {}, 'errorSlot'),
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'el-date-picker',
field: 'time',
label: '出生日期',
required: true,
error: 'errorSlot',
fieldProps: {
type: 'daterange',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
},
},
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:columns="columns"
:options="options"
:action="false"
:search="{ labelWidth: '80px' }"
:request="request"
>
<template #labelSlot>
<span>性别</span>
</template>
<template #errorSlot>
<span>出生日期必填</span>
</template>
</z-crud>
</template>
联动
使用hide
配置表单项显隐。性别选择male
则展示出生日期筛选项。
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
time: [],
})
const tableData = ref([])
const visible = ref(false)
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
field: 'name',
label: '姓名',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
field: 'gender',
label: '性别',
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'el-date-picker',
field: 'time',
label: '出生日期',
hide: () => !visible.value,
fieldProps: {
type: 'daterange',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
},
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function handleClick() {
visible.value = !visible.value
}
</script>
<template>
<el-button @click="handleClick">
点击
</el-button>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:options="options"
:columns="columns"
:search="{ labelWidth: '80px' }"
:action="false"
:request="request"
/>
</template>
操作按钮
按钮操作会有search
和reset
事件,已经内置重置操作和校验操作。支持自定义。
详情请查看z-filter-form
组件文档。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
time: [],
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
field: 'name',
label: '姓名',
required: true,
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
field: 'gender',
label: '性别',
required: true,
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'el-date-picker',
field: 'time',
label: '出生日期',
required: true,
fieldProps: {
type: 'daterange',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
},
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function handleSearch() {
console.log(formData.value, 'formData')
}
function handleReset() {
console.log(formData.value, 'formData')
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:columns="columns"
:options="options"
:search="{ labelWidth: '80px' }"
:action="false"
:request="request"
@search="handleSearch"
@reset="handleReset"
/>
</template>
默认收起
配置search
的collapsed
为false
,表单会默认收起。
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
time: [],
})
const tableData = ref([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
field: 'name',
label: '姓名',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
field: 'gender',
label: '性别',
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'el-date-picker',
field: 'time',
label: '出生日期',
fieldProps: {
type: 'daterange',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
},
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
const request = ref({
searchApi: mockApi,
})
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
v-model:loading="loading"
:columns="columns"
:options="options"
:search="{ labelWidth: '80px', collapsed: false }"
:action="false"
:request="request"
/>
</template>
装饰组件
配置formDecorator
和crudDecorator
可以配置筛选表单和表格的背景。name
字段可以是div
、span
等标签,也可以是全局注册组件名称。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { result: { page: number, pageSize: number, list: RowData[], total: number } }
const loading = ref(false)
const formData = ref({
name: '',
gender: '',
age: '',
})
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'name',
label: '姓名',
search: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
search: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
search: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
page: 1,
pageSize: 2,
total: 4,
})
function mockApi(params: any): Promise<GetTableDataRes> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const params = {
...pagination.value,
...formData.value,
}
const res = await mockApi(params)
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
function handleSearch() {
pagination.value.page = 1
getTableData()
}
getTableData()
</script>
<template>
<z-crud
v-model:pagination="pagination"
v-model:data="tableData"
v-model:formData="formData"
:columns="columns"
:options="options"
:loading="loading"
:action="false"
:form-decorator="{ name: 'div', style: { border: '1px solid #e4e7ed', paddingTop: '18px' } }"
:table-decorator="{ name: 'el-card', shadow: 'hover' }"
@refresh="getTableData"
@search="handleSearch"
@reset="handleSearch"
/>
</template>
z-crud查询表单相关属性
属性名 | 说明 | 类型 | 默认值 |
---|---|---|---|
modelValue:formData | 查询表单数据 | object | — |
detail | 详情配置 | boolean / object / ({ row, tableRef }) => void | true |
form | 查询、新增、编辑和查看表单属性配置 | object | — |
action | 操作项是否展示(内置的删除、编辑等按钮) | boolean | true |
edit | 编辑配置 | boolean / object | true |
add | 新增配置 | boolean / object | true |
delete | 删除配置 | boolean / ({ row, tableRef, getTableData }) => void / object | |
search | 查询配置 | boolean / object | true |
request | 接口配置 | object | — |
paginationStorage | 分页缓存 | boolean | false |
formStorage | 查询表单数据缓存 | boolean | false |
formDecorator | 表单背景 | object | { name: 'el-card' } |
tableDecorator | 表格背景 | object | { name: 'el-card' } |
search属性
属性名 | 说明 | 类型 | 默认值 |
---|---|---|---|
collapsed | 表单默认展开收起 | boolean | true |
searchButtonProps | 查询按钮属性配置 | object | — |
searchButtonLabel | 查询按钮文案 | string | 查询 |
searchButtonLoading | 查询按钮加载状态 | boolean | — |
resetButtonProps | 重置按钮属性配置 | object | — |
resetButtonLabel | 重置按钮文案 | string | 重置 |
resetButtonLoading | 重置按钮加载状态 | boolean | — |
rules | 表单验证规则 | object | — |
label-position | 表单域标签的位置, 当设置为 left 或 right 时,则也需要设置 label-width 属性 | enum | right |
label-width | 标签的长度,例如 '50px' 。 作为 Form 直接子元素的 form-item 会继承该值。 可以使用 auto 。 | string / number | '' |
label-suffix | 表单域标签的后缀 | string | '' |
hide-required-asterisk | 是否隐藏必填字段标签旁边的红色星号。 | boolean | false |
require-asterisk-position | 星号的位置。 | left / right | left |
show-message | 是否显示校验错误信息 | boolean | true |
inline-message | 是否以行内形式展示校验信息 | boolean | false |
status-icon | 是否在输入框中显示校验结果反馈图标 | boolean | false |
validate-on-rule-change | 是否在 rules 属性改变后立即触发一次验证 | boolean | true |
size | 用于控制该表单内组件的尺寸 | large / default / small | — |
disabled | 是否禁用该表单内的所有组件。 如果设置为 true , 它将覆盖内部组件的 disabled 属性 | boolean | false |
z-crud查询表单方法
名称 | 说明 | 类型 |
---|---|---|
validate | 对整个表单的内容进行验证。 接收一个回调函数,或返回 Promise 。 | Function |
validateField | 验证具体的某个字段。 | Function |
resetFields | 重置该表单项,将其值重置为初始值,并移除校验结果 | Function |
scrollToField | 滚动到指定的字段 | Function |
clearValidate | 清理某个字段的表单验证信息。 | Function |
表单项属性
属性名 | 说明 | 类型 | 默认值 |
---|---|---|---|
component | 表单项组件 | string / () => VNode / Component | — |
field | 字段名 | string | — |
fieldProps | component 组件属性 | object | — |
formItemProps | formItem 组件属性 | object | — |
label | 表单标签名 | string / () => VNode | — |
hide | 显隐 | boolean / (formData) => boolean | — |
show | 使用v-show 显隐 | boolean / (formData) => boolean | — |
slot | 表单项自定义内容插槽 | string | — |
render | 表单项自定义内容render | () => VNode | — |
required | 表单项是否必填 | boolean | — |
rules | 该表单项校验规则 | boolean | — |
error | 错误信息 | string / () => VNode | — |
tooltip | 提示信息 | string / () => VNode | — |
extra | 额外信息 | string / () => VNode | — |
formItemProps属性
属性名 | 说明 | 类型 | Default |
---|---|---|---|
tooltip | 提示文案 | string / () => VNode | — |
extra | 额外信息 | string / () => VNode | — |
colon | 冒号 | boolean | — |
label | 标签文本 | string / () => VNode | — |
label-width | 标签宽度,例如 '50px' 。 可以使用 auto 。 | string / number | '' |
required | 是否为必填项,如不设置,则会根据校验规则确认 | boolean | — |
rules | 表单验证规则, 具体配置见下表, 更多内容可以参考async-validator | object | — |
error | 表单域验证错误时的提示信息。设置该值会导致表单验证状态变为 error,并显示该错误信息。 | string / () => VNode | — |
show-message | 是否显示校验错误信息 | boolean | true |
inline-message | 是否在行内显示校验信息 | string / boolean | '' |
size | 用于控制该表单域下组件的默认尺寸 | large / default / small | — |
for | 和原生标签相同能力 | string | — |
validate-status | formItem 校验的状态 | error / validating / success | — |
z-crud查询表单相关事件
事件名 | 说明 | 类型 |
---|---|---|
update:formData | 表单项数据 | Function |
reset | 重置 | Function |
search | 查询 | Function |