How to Build a Data Dashboard System: JSON Configuration, Component Containers, and Remote Component Store
This article explains the concepts, design of JSON configuration structures, component container patterns, editing side form generation, remote component store integration, static publishing, version management, and inter‑component communication for constructing a data dashboard platform using modern frontend technologies.
1. What Is a Data Dashboard and What Is It Used For
Before defining a data dashboard, we need to understand data visualization, which encodes quantitative information using charts, graphs, and infographics to make complex data easier to comprehend. A data dashboard is the vehicle for visualized data, presenting it through thoughtful layout and design.
The dashboard serves two main purposes: (1) Situation awareness – it lets decision‑makers clearly see product operation status; (2) Problem solving – it enables analysts to discover anomalies and propose corrective actions.
2. Configuration File Data Structure Design
Assume a dashboard page is described by a JSON file that records component information such as size, position, and title. An example structure is shown below:
[
{
"type": "line",
"id": 1,
"data": [],
"title": "货物销售情况",
"layout": { x: 0, y: 0, w: 3, h: 2 }
},
{
"type": "bar",
"id": 2,
"data": [],
"title": "货物留存情况",
"layout": { i: 'c', x: 3, y: 0, w: 3, h: 2 }
}
]With this structure, each component can be rendered by passing its configuration (e.g., {type:line} ) to the appropriate widget.
3. Component Container
After components and their configurations are ready, the root component simply iterates over them:
<div>
{widgets.map(widget => {
const WidgetComp = getWidgetComp(widget.type);
return <WidgetComp config={widget} key={widget.id} />;
})}
</div>To avoid duplicated logic (data fetching, layout handling, etc.) across components, a unified container can be introduced:
const Widget = ({config}) => {
// component click event
const handleClick = () => {/* ... */};
// layout handling
const handleLayout = () => {/* ... */};
// fetch component data
const getWidgetData = () => {/* ... */};
// other shared logic
...
const WidgetComp = getWidgetComp(widget.type);
return <WidgetComp config={widget} />;
};The root component then renders the container instead of the raw widget:
<div>
{widgets.map(widget => <Widget config={widget} key={widget.id} />)}
</div>4. Editing Side – Configuring Components
The editing side provides a UI for users to modify component configurations. For a line component that needs a customizable name, a simple form is used:
<Form form={form}>
<Item name="name" label="名称" rules={[{ required: true, message: '请输入' }]}>
<Input placeholder="请输入" />
</Item>
</Form>When requirements change (e.g., a bar component needs a configurable width), the form generation logic grows with conditional branches. To avoid an ever‑expanding if‑else chain, a unified configurator and a schema file per component are introduced. The schema records editable fields and default models, for example:
{
"fields": [{ "label": "名称", "type": "input", "name": "name" }],
"models": { "name": "默认名称" }
}The configurator merges backend data with the schema’s default models and renders the form dynamically.
5. Loading Components from a Remote Store
To keep the bundle size manageable as component count grows, components are uploaded to a static server with version tags. The dashboard can then load components remotely based on the project’s configuration.
A full‑featured component store includes online editing/upload, review, publishing, and management (publish/unpublish/delete/download/version).
6. Static Publishing
After editing, changes are not immediately visible to end users. A publish step ensures that only approved configurations are served. Static publishing also isolates projects: if a component is updated, only projects that republish the new version are affected.
7. Version Management for Components and Containers
Each component receives a version number upon upload. Projects that lock a specific component version remain unaffected by later updates. Containers, which encapsulate shared logic, also require versioning because any change to a container impacts all projects that use it.
8. Component Communication
Components often need to communicate (e.g., clicking component A triggers an action in component B). A publish‑subscribe event hub is used: publishers emit events, the hub stores them, and subscribers react accordingly.
export default {
publish: [
{ name: "电子卖场预警发布/流程/onChange", reflectName: "onChange" }
],
subscribe: [
{ list: ["电子卖场预警发布/onChange"], action: "setClass", handler: "function parse(params) { return {}; }" }
]
};9. References
1. "How to Design a Visual‑Building Platform’s Component Store" (https://juejin.cn/post/6986824393653485605)
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.