API
Grid
Constructor
ts
declare const options: IGridOptions | undefined
const grid = new Grid(options)createGrid
ts
declare const options: IGridOptions | undefined
const grid = createGrid(options)createGridis a lightweight wrapper aroundnew Grid(options)and it returns a grid instances which wrapped by markRaw.
Constructor Options Table
| Option | Type | Default | Description |
|---|---|---|---|
maxRows | number | Infinity | Maximum rows |
maxColumns | number | number[] | Infinity | Maximum columns, supports breakpoint arrays |
minColumns | number | number[] | 1 | Minimum columns, supports breakpoint arrays |
maxWidth | number | number[] | Infinity | Max column width, supports breakpoint arrays |
minWidth | number | number[] | 100 | Min column width, supports breakpoint arrays |
breakpoints | number[] | [720, 1280, 1920] | Breakpoint list |
columnGap | number | number[] | 8 | Column gap, supports breakpoint arrays |
rowGap | number | number[] | 4 | Row gap, supports breakpoint arrays |
colWrap | boolean | boolean[] | true | Whether column wrapping is enabled |
strictAutoFit | boolean | false | Enforce strict min/max width boundaries |
shouldVisible | (node: GridNode, grid: Grid) => boolean | - | Custom node visibility rule |
onDigest | (grid: Grid) => void | - | Called after each layout digest |
onInitialized | (grid: Grid) => void | - | Called after initial layout completes |
connect
ts
declare const container: HTMLElement
const dispose = grid.connect(container)- Returns
disposeto clean upResizeObserver/MutationObserverand internal state.
IGridOptions
ts
interface IGridOptions {
maxRows?: number
maxColumns?: number | number[]
minColumns?: number | number[]
maxWidth?: number | number[]
minWidth?: number | number[]
breakpoints?: number[]
columnGap?: number
rowGap?: number
colWrap?: boolean
strictAutoFit?: boolean
shouldVisible?: (node: GridNode, grid: Grid<HTMLElement>) => boolean
onDigest?: (grid: Grid<HTMLElement>) => void
onInitialized?: (grid: Grid<HTMLElement>) => void
}GridNode
ts
type GridNode = {
index?: number
visible?: boolean
column?: number
shadowColumn?: number
row?: number
shadowRow?: number
span?: number
originSpan?: number
element?: HTMLElement
}Grid Runtime State
| Field | Type | Description |
|---|---|---|
width | number | Container width |
height | number | Container height |
columns | number | Current columns |
rows | number | Current rows |
templateColumns | string | Current grid-template-columns |
gap | string | Current CSS gap value |
breakpoint | number | Current breakpoint index |
ready | boolean | Whether initial layout has completed |
Grid Span
data-grid-span defines how many columns a node occupies:
data-grid-span="n": Occupyncolumns.data-grid-span="-1": Auto-fill from the current column to the end of the row.
The demo below toggles the Actions block between -1 and 1 so you can compare the layout behavior:
<script setup lang="ts">
import { Grid } from '@silver-formily/grid'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
const containerRef = ref<HTMLElement | null>(null)
const useAutoFill = ref(true)
const templateColumns = ref('repeat(4,minmax(0,1fr))')
const gap = ref('8px 8px')
const columns = ref(4)
const items = computed(() => [
{ key: 'name', label: 'Name', span: 1 },
{ key: 'email', label: 'Email', span: 1 },
{
key: 'actions',
label: 'Actions',
span: useAutoFill.value ? -1 : 1,
accent: true,
},
{ key: 'phone', label: 'Phone', span: 1 },
{ key: 'company', label: 'Company', span: 2 },
{ key: 'city', label: 'City', span: 1 },
{ key: 'zip', label: 'Zip', span: 1 },
])
let dispose: (() => void) | undefined
const grid = new Grid({
minColumns: 4,
maxColumns: 4,
minWidth: 70,
maxWidth: 160,
columnGap: 8,
rowGap: 8,
onDigest(current) {
templateColumns.value = current.templateColumns
gap.value = current.gap
columns.value = current.columns
},
})
onMounted(() => {
if (!containerRef.value)
return
dispose = grid.connect(containerRef.value)
})
onBeforeUnmount(() => {
dispose?.()
})
</script>
<template>
<div>
<p>
<label><input v-model="useAutoFill" type="checkbox"> Use <code>data-grid-span="-1"</code> for Actions</label>
</p>
<p>
columns={{ columns }} / Actions span={{ useAutoFill ? -1 : 1 }}
</p>
<div ref="containerRef" class="grid-board" :style="{ gridTemplateColumns: templateColumns, gap }">
<div
v-for="item in items"
:key="item.key"
class="grid-card"
:class="{ accent: item.accent }"
:data-grid-span="item.span"
>
<strong>{{ item.label }}</strong>
<span>data-grid-span={{ item.span }}</span>
</div>
</div>
</div>
</template>
<style scoped>
.grid-board {
display: grid;
}
.grid-card {
border: 1px solid var(--vp-c-divider);
border-radius: 10px;
padding: 10px;
background: var(--vp-c-bg-soft);
display: flex;
flex-direction: column;
gap: 6px;
}
.grid-card.accent {
border-color: var(--vp-c-brand-1);
background: color-mix(in srgb, var(--vp-c-brand-1) 12%, var(--vp-c-bg-soft));
}
</style>columns=4 / Actions span=-1
Namedata-grid-span=1
Emaildata-grid-span=1
Actionsdata-grid-span=-1
Phonedata-grid-span=1
Companydata-grid-span=2
Citydata-grid-span=1
Zipdata-grid-span=1
查看源码