PageDesigner 页面设计器
可视化页面设计器,支持拖拽组件、自由布局、数据绑定等功能。
基础用法
最基础的页面设计器用法。
vue
<template>
<NPageDesigner
:schema="schema"
@save="handleSave"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [],
dataFlow: [],
})
const handleSave = (data) => {
console.log('保存页面:', data)
}
</script>使用模板
使用预设模板快速创建页面。
vue
<template>
<NPageDesigner
:schema="schema"
:templates="templates"
@save="handleSave"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [],
dataFlow: [],
})
const templates = [
{
id: 'blank',
name: '空白页面',
description: '从空白页面开始设计',
schema: {
components: [],
dataFlow: [],
},
},
{
id: 'form',
name: '表单页面',
description: '包含常用表单组件的页面',
schema: {
components: [
{ type: 'input', props: { label: '姓名' } },
{ type: 'select', props: { label: '性别' } },
],
dataFlow: [],
},
},
]
const handleSave = (data) => {
console.log('保存页面:', data)
}
</script>自由布局
支持自由拖拽和定位组件。
vue
<template>
<NPageDesigner
:schema="schema"
layout="free"
@save="handleSave"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
position: { x: 100, y: 100, width: 120, height: 40 },
},
],
dataFlow: [],
})
const handleSave = (data) => {
console.log('保存页面:', data)
}
</script>网格布局
使用网格布局系统。
vue
<template>
<NPageDesigner
:schema="schema"
layout="grid"
:gridSize="12"
@save="handleSave"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
grid: { col: 1, row: 1, colSpan: 2, rowSpan: 1 },
},
],
dataFlow: [],
})
const handleSave = (data) => {
console.log('保存页面:', data)
}
</script>数据绑定
支持组件之间的数据绑定。
vue
<template>
<NPageDesigner
:schema="schema"
@save="handleSave"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: 'input1',
type: 'input',
props: { label: '输入框' },
},
{
id: 'text1',
type: 'text',
props: { content: '' },
},
],
dataFlow: [
{
source: { componentId: 'input1', output: 'value' },
target: { componentId: 'text1', input: 'content' },
},
],
})
const handleSave = (data) => {
console.log('保存页面:', data)
}
</script>自定义组件
注册自定义组件。
vue
<template>
<NPageDesigner
:schema="schema"
:customComponents="customComponents"
@save="handleSave"
/>
</template>
<script setup>
import { ref } from 'vue')
import MyComponent from './MyComponent.vue')
const schema = ref({
components: [],
dataFlow: [],
})
const customComponents = [
{
type: 'my-component',
name: '自定义组件',
icon: 'custom',
component: MyComponent,
defaultProps: {
text: '默认文本',
},
},
]
const handleSave = (data) => {
console.log('保存页面:', data)
}
</script>只读模式
设置 readonly 属性为 true 进入只读模式。
vue
<template>
<NPageDesigner
:schema="schema"
readonly
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
position: { x: 100, y: 100, width: 120, height: 40 },
},
],
dataFlow: [],
})
</script>预览模式
设置 preview 属性为 true 进入预览模式。
vue
<template>
<div>
<NButton @click="preview = !preview">
{{ preview ? '编辑' : '预览' }}
</NButton>
<NPageDesigner
:schema="schema"
:preview="preview"
/>
</div>
</template>
<script setup>
import { ref } from 'vue')
const preview = ref(false)
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
position: { x: 100, y: 100, width: 120, height: 40 },
},
],
dataFlow: [],
})
</script>禁用拖拽
设置 draggable 属性为 false 禁用拖拽。
vue
<template>
<NPageDesigner
:schema="schema"
:draggable="false"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
position: { x: 100, y: 100, width: 120, height: 40 },
},
],
dataFlow: [],
})
</script>禁用调整大小
设置 resizable 属性为 false 禁用调整大小。
vue
<template>
<NPageDesigner
:schema="schema"
:resizable="false"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
position: { x: 100, y: 100, width: 120, height: 40 },
},
],
dataFlow: [],
})
</script>显示网格
设置 showGrid 属性为 true 显示网格。
vue
<template>
<NPageDesigner
:schema="schema"
showGrid
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
position: { x: 100, y: 100, width: 120, height: 40 },
},
],
dataFlow: [],
})
</script>吸附对齐
设置 snap 属性为 true 启用吸附对齐。
vue
<template>
<NPageDesigner
:schema="schema"
snap
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [
{
id: '1',
type: 'button',
props: { text: '按钮' },
position: { x: 100, y: 100, width: 120, height: 40 },
},
],
dataFlow: [],
})
</script>事件监听
vue
<template>
<NPageDesigner
:schema="schema"
@save="handleSave"
@select="handleSelect"
@deselect="handleDeselect"
@dragStart="handleDragStart"
@dragEnd="handleDragEnd"
@resizeStart="handleResizeStart"
@resizeEnd="handleResizeEnd"
/>
</template>
<script setup>
import { ref } from 'vue')
const schema = ref({
components: [],
dataFlow: [],
})
const handleSave = (data) => {
console.log('保存:', data)
}
const handleSelect = (component) => {
console.log('选中:', component)
}
const handleDeselect = () => {
console.log('取消选中')
}
const handleDragStart = (component) => {
console.log('开始拖拽:', component)
}
const handleDragEnd = (component) => {
console.log('结束拖拽:', component)
}
const handleResizeStart = (component) => {
console.log('开始调整大小:', component)
}
const handleResizeEnd = (component) => {
console.log('结束调整大小:', component)
}
</script>API
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| schema | 页面 schema | PageSchema | — |
| templates | 预设模板列表 | PageTemplate[] | [] |
| customComponents | 自定义组件列表 | CustomComponent[] | [] |
| layout | 布局模式 | 'free' | 'grid' | 'free' |
| gridSize | 网格大小 | number | 12 |
| readonly | 是否只读模式 | boolean | false |
| preview | 是否预览模式 | boolean | false |
| draggable | 是否可拖拽 | boolean | true |
| resizable | 是否可调整大小 | boolean | true |
| showGrid | 是否显示网格 | boolean | false |
| snap | 是否启用吸附对齐 | boolean | true |
PageSchema
| 属性 | 说明 | 类型 |
|---|---|---|
| components | 组件列表 | LayoutNode[] |
| dataFlow | 数据流配置 | DataFlowConfig[] |
LayoutNode
| 属性 | 说明 | 类型 |
|---|---|---|
| id | 组件 ID | string |
| type | 组件类型 | string |
| props | 组件属性 | Record<string, any> |
| position | 位置和尺寸(自由布局) | { x: number; y: number; width: number; height: number } |
| grid | 网格位置(网格布局) | { col: number; row: number; colSpan: number; rowSpan: number } |
DataFlowConfig
| 属性 | 说明 | 类型 |
|---|---|---|
| source | 数据源 | { componentId: string; output: string } |
| target | 数据目标 | { componentId: string; input: string } |
Events
| 事件名 | 说明 | 类型 |
|---|---|---|
| save | 保存时触发 | (schema: PageSchema) => void |
| select | 选中组件时触发 | (component: LayoutNode) => void |
| deselect | 取消选中时触发 | () => void |
| dragStart | 开始拖拽时触发 | (component: LayoutNode) => void |
| dragEnd | 结束拖拽时触发 | (component: LayoutNode) => void |
| resizeStart | 开始调整大小时触发 | (component: LayoutNode) => void |
| resizeEnd | 结束调整大小时触发 | (component: LayoutNode) => void |
方法
| 方法名 | 说明 | 类型 |
|---|---|---|
| save | 保存页面 | () => void |
| undo | 撤销操作 | () => void |
| redo | 重做操作 | () => void |
| clear | 清空所有组件 | () => void |
| getSchema | 获取当前 schema | () => PageSchema |
| setSchema | 设置 schema | (schema: PageSchema) => void |