# Luban H5 Work/Pages/Elements JSON Schema: Structure, Fields, and Implementation

> Explore the Luban H5 JSON schema structure for work pages and elements. Understand the hierarchy and key fields for H5 project implementation. Learn how to define components, styles, and animations.

- Repository: [小小鲁班/luban-h5](https://github.com/ly525/luban-h5)
- Tags: api-reference
- Published: 2026-03-06

---

**The Luban H5 JSON schema organizes H5 projects into a three-tier hierarchy where the root `pages` object maps page IDs to page configurations, each containing a `components` object that defines individual elements with properties like `type`, `props`, `style`, `animation`, and `events`.**

The `ly525/luban-h5` repository stores interactive H5 page configurations in a strict JSON format that powers its open-source visual page builder. Understanding the **work/pages/elements JSON schema** is essential for developers customizing project exports, extending the component library, or integrating the renderer into custom pipelines.

## Overview of the Hierarchical Schema

The schema follows a tree structure with three primary levels. At the top, the **work** object contains a **pages** map. Each page entry holds metadata and a **components** collection (synonymous with elements). Every component represents a visual element with configurable properties.

### The Root `pages` Object

The root of the work JSON contains a **`pages`** field, which is an object (dictionary) rather than an array. Keys are unique page identifiers (e.g., `page_1`, `page_2`), and values are page configuration objects containing `name`, `background`, `width`, `height`, and the `components` map. This structure allows O(1) page lookup and is defined in [`back-end/h5-api/api/work/documentation/1.0.0/work.json`](https://github.com/ly525/luban-h5/blob/main/back-end/h5-api/api/work/documentation/1.0.0/work.json).

### Page Configuration and the `components` Map

Within each page, the **`components`** property stores all visual elements for that canvas. Keys are element IDs (e.g., `elem_123`), and values are element definition objects. This map enables direct element access for updates, as seen in [`front-end/h5/src/store/modules/work.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/store/modules/work.js) where mutations modify specific `components` entries by ID.

### Element Object Structure

An element object defines a single UI component through seven primary fields: **`type`**, **`component`**, **`props`**, **`style`**, **`animation`**, **`events`**, **`dataSource`**, and **`children`**. All fields are optional except `type` and `component`, which are required for the renderer to instantiate the correct Vue component. The schema is flexible, allowing elements to omit unused sections such as `animation` or `dataSource`.

## Detailed Element Property Reference

Each property in an element object controls a specific aspect of rendering, styling, or behavior.

### Component Identification (`type` and `component`)

The **`type`** field specifies the UI category (e.g., `image`, `text`, `button`, `shape`, `group`), determining which icon and default settings appear in the editor. The **`component`** field provides the internal renderer name (e.g., `Image`, `TextBlock`) used by [`front-end/h5/src/components/Renderer.vue`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/Renderer.vue) to map JSON definitions to Vue component registrations.

### Styling and Positioning (`style` object)

The **`style`** object contains CSS-like properties defining layout and appearance: `width`, `height`, `top`, `left`, `rotate` (rotation in degrees), `opacity` (0-1), `border`, and `boxShadow`. All measurements are stored as numbers representing pixels or as hex color strings, enabling the renderer to apply inline styles directly.

### Animation Configuration (`animation`)

The optional **`animation`** object controls entrance or emphasis effects with properties: `type` (animation name like `fadeIn` or `slideUp`), `duration` (milliseconds), `delay` (milliseconds), and `easing` (timing function such as `easeOutQuad`). If omitted, the element renders statically without motion, as handled by the animation runtime in the front-end engine.

### Event Handling (`events`)

The **`events`** object maps DOM event names to handler definitions. Values are stringified JavaScript functions or global function references (e.g., `"click": "function() { alert('clicked'); }"`). The renderer attaches these listeners during component mount, parsing the strings via `new Function()` or mapping to predefined actions.

### Data Binding and Nesting (`dataSource` and `children`)

The **`dataSource`** field configures dynamic data fetching, containing `type` (`api` or `mock`), `url`, `method`, and `params`, allowing elements to render live content. The **`children`** field is an array of element ID strings used exclusively by container-type components (e.g., `group`), establishing a parent-child hierarchy that the renderer resolves into nested Vue components.

## Working with the Schema in Code

Developers interact with the schema by reading the work JSON, mutating the `components` map, and triggering re-renders.

### Rendering a Page from JSON

To render a page, iterate over the `components` map and instantiate the corresponding Vue component for each entry.

```javascript
import { renderComponent } from '@/utils/renderer';

function renderPage(pageData) {
  Object.entries(pageData.components).forEach(([elemId, element]) => {
    renderComponent(element, elemId); // Maps type to Vue component
  });
}

```

### Programmatically Adding Elements

You can mutate the `work` object directly to inject new elements at runtime.

```javascript
function addTextElement(work, pageId, textContent) {
  const page = work.pages[pageId];
  const newId = `elem_${Date.now()}`;
  page.components[newId] = {
    type: 'text',
    component: 'TextBlock',
    props: { text: textContent },
    style: { top: 100, left: 50, fontSize: 24, color: '#333' },
    animation: { type: 'fadeIn', duration: 300 }
  };
  return newId;
}

```

### Exporting the Work Configuration

Serialize the entire work object to JSON for persistence or server-side storage.

```javascript
import fs from 'fs';
const workJson = JSON.stringify(work, null, 2);
fs.writeFileSync('work-config.json', workJson);

```

## Key Implementation Files

The following source files define and consume the schema:

- [[`back-end/h5-api/api/work/models/Work.settings.json`](https://github.com/ly525/luban-h5/blob/main/back-end/h5-api/api/work/models/Work.settings.json)](https://github.com/ly525/luban-h5/blob/master/back-end/h5-api/api/work/models/Work.settings.json) – Defines default work structure and validation rules.
- [[`back-end/h5-api/api/work/documentation/1.0.0/work.json`](https://github.com/ly525/luban-h5/blob/main/back-end/h5-api/api/work/documentation/1.0.0/work.json)](https://github.com/ly525/luban-h5/blob/master/back-end/h5-api/api/work/documentation/1.0.0/work.json) – Provides a complete example of the JSON schema including pages and components.
- [[`back-end/h5-api/extensions/documentation/documentation/1.0.0/full_documentation.json`](https://github.com/ly525/luban-h5/blob/main/back-end/h5-api/extensions/documentation/documentation/1.0.0/full_documentation.json)](https://github.com/ly525/luban-h5/blob/master/back-end/h5-api/extensions/documentation/documentation/1.0.0/full_documentation.json) – Aggregated API documentation referencing the work entity schema.
- [[`front-end/h5/src/store/modules/work.js`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/store/modules/work.js)](https://github.com/ly525/luban-h5/blob/master/front-end/h5/src/store/modules/work.js) – Vuex store managing work state and mutations on the `pages` and `components` objects.
- [[`front-end/h5/src/components/Renderer.vue`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/Renderer.vue)](https://github.com/ly525/luban-h5/blob/master/front-end/h5/src/components/Renderer.vue) – Core component that traverses the schema to render the visual tree and resolve nested children.

## Summary

- The **work** object contains a **pages** map where keys are page IDs and values hold page metadata plus a **components** object.
- Each **element** in `components` requires `type` and `component` fields, with optional `props`, `style`, `animation`, `events`, `dataSource`, and `children`.
- The **style** object uses pixel-based numeric values for positioning and sizing.
- **Animation** and **events** are optional objects controlling motion and interactivity.
- **DataSource** enables API bindings, while **children** supports nested group structures.
- Source code in [`back-end/h5-api/api/work/documentation/1.0.0/work.json`](https://github.com/ly525/luban-h5/blob/main/back-end/h5-api/api/work/documentation/1.0.0/work.json) and [`front-end/h5/src/components/Renderer.vue`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/Renderer.vue) demonstrates the schema implementation.

## Frequently Asked Questions

### What is the root structure of a Luban H5 work JSON?

The root is an object containing a **`pages`** field, which is a dictionary mapping page IDs (like `page_1`) to page objects. Each page object includes layout metadata (`width`, `height`, `background`) and a **`components`** object that holds all elements for that page, as defined in [`back-end/h5-api/api/work/documentation/1.0.0/work.json`](https://github.com/ly525/luban-h5/blob/main/back-end/h5-api/api/work/documentation/1.0.0/work.json).

### How are elements organized within a page?

Elements are stored in the **`components`** object (also referred to as the elements map) inside each page definition. The keys are unique element IDs (e.g., `elem_123`), and the values are element configuration objects containing `type`, `props`, `style`, and other properties, enabling direct key-based access for rapid updates.

### What properties define an element's appearance and behavior?

An element's appearance is controlled by the **`style`** object (position, size, rotation, opacity) and **`props`** (content-specific attributes like text or image src). Behavior is governed by **`events`** (click handlers) and **`animation`** (entrance effects), while **`dataSource`** configures dynamic content fetching from external APIs.

### How does the renderer handle nested element groups?

When an element has a **`children`** array (used by group-type components), the renderer recursively processes each child ID listed in the array, looking up the corresponding element definition in the page's `components` map. This creates a nested DOM tree within the parent container, as implemented in [`front-end/h5/src/components/Renderer.vue`](https://github.com/ly525/luban-h5/blob/main/front-end/h5/src/components/Renderer.vue).