Skip to content

Hooks 组合模式

AutoCrud 是开箱即用的一体化组件,适合大多数场景。但当你需要完全控制布局、交互流程或混合自定义 UI时,可以直接使用底层 hooks 和子组件进行自由组合。

何时选择组合模式

需求AutoCrudHooks 组合
标准 CRUD 页面推荐可以但没必要
自定义页面布局(左右分栏、tabs 等)受限推荐
需要在多个组件间共享列表状态需 ref/expose推荐
完全自定义搜索/表格/表单交互slot 能力受限推荐

数据流

核心原则:hooks 管理状态,组件负责渲染。每个 hook 的返回值直接传给对应组件的 props。

完整示例

vue
<script setup lang="ts">
import { useCrudForm, useCrudList, useCrudSelection } from '@uozi/vito-core'
import { CrudForm, CrudSearch, CrudTable } from '@uozi/vito-naive-ui'
import { ref } from 'vue'
import { adapter, columns, fields } from './schema'

// 1. 列表
const list = useCrudList({
  adapter,
  initialQuery: {},
  initialPageSize: 20,
})

// 2. 行选择
const selection = useCrudSelection({
  rows: list.rows,
  getId: row => row.id,
})

// 3. 表单
const form = useCrudForm({ fields })
const formVisible = ref(false)

function openCreate() {
  form.reset()
  form.setMode('create')
  formVisible.value = true
}

function openEdit(row: any) {
  form.reset(row)
  form.setMode('edit')
  formVisible.value = true
}

async function handleSubmit(data: any) {
  if (form.mode.value === 'create') {
    await adapter.create!(data)
  } else {
    const id = (form.model as any).id
    await adapter.update!(id, data)
  }
  formVisible.value = false
  await list.refresh()
}
</script>

<template>
  <div>
    <!-- 搜索区 -->
    <CrudSearch :list="list" :fields="fields" />

    <!-- 工具栏 -->
    <div style="margin-bottom: 16px">
      <NButton type="primary" @click="openCreate">新增</NButton>
      <span v-if="selection.selectedCount.value > 0" style="margin-left: 12px">
        已选 {{ selection.selectedCount.value }} 项
        <NButton size="small" @click="selection.clear()">清除</NButton>
      </span>
    </div>

    <!-- 表格 -->
    <CrudTable
      :list="list"
      :columns="columns"
      :selection="selection"
      :row-key="(row) => row.id"
      show-actions-column
    >
      <template #row-actions="{ row }">
        <NButton size="small" @click="openEdit(row)">编辑</NButton>
      </template>
    </CrudTable>

    <!-- 表单 -->
    <CrudForm
      v-model:visible="formVisible"
      :form="form"
      :fields="fields"
      display-mode="drawer"
      @submit="handleSubmit"
    />
  </div>
</template>

各 Hook 职责

Hook职责传给组件
useCrudList分页、查询、排序、数据拉取CrudSearch.listCrudTable.list
useCrudForm表单模型、模式、变更追踪CrudForm.form
useCrudSelection行选择、跨页选择CrudTable.selection
useCrudRouteSync查询条件 ↔ URL 双向同步无需传给组件,自动工作
useCrudActions动态操作注册/按区域分组手动渲染或传给自定义组件

添加路由同步

ts
import { useCrudRouteSync } from '@uozi/vito-core'
import { useRoute, useRouter } from 'vue-router'

const router = useRouter()
const route = useRoute()

useCrudRouteSync({
  query: list.query,
  setQuery: list.setQuery,
  router,
  route,
  queryKey: 'q',
})

只要调用了 useCrudRouteSynclist.query 的变化就会自动同步到 URL,页面刷新后也会自动从 URL 恢复查询条件。

使用 Expose 访问 AutoCrud 内部状态

如果你主要使用 AutoCrud,但偶尔需要从外部访问内部状态,可以通过 ref 获取 expose:

vue
<script setup lang="ts">
import { ref } from 'vue'

const crudRef = ref()

function handleCustomAction() {
  // 访问内部 list 状态
  console.log(crudRef.value.list.rows.value)

  // 手动刷新
  crudRef.value.refresh()

  // 打开创建表单
  crudRef.value.openCreate()

  // 打开编辑表单
  crudRef.value.openEdit(someRow)

  // 访问选择状态
  console.log(crudRef.value.selection.selectedIds.value)
}
</script>

<template>
  <AutoCrud ref="crudRef" :adapter="adapter" :fields="fields" :columns="columns" />
</template>

AutoCrud expose 的属性:

属性类型说明
listUseCrudListReturn列表状态和操作
selectionUseCrudSelectionReturn选择状态和操作
formUseCrudFormReturn表单状态和操作
refresh()() => Promise<void>刷新列表
openCreate()() => void打开新增表单
openEdit(row)(row: Row) => void打开编辑表单

Made with VitePress