Kupola
零框架依赖的声明式 UI 组件系统,适用于任何服务端渲染 Web 应用。
HTMX(数据获取)+ Alpine.js(声明式交互)+ Bootstrap(组件丰富度)— 合为一个零依赖包。
50+ UI 组件
按钮、输入框、卡片、模态框、表格、日期选择器、热力图等
响应式数据绑定
基于 Proxy 的双向绑定 data-bind,ref() / store()
双主题 + 11 品牌色
暗色优先,亮色切换,中国传统色品牌主题
后端无关
Flask / Django / FastAPI / Gin / Spring Boot / ASP.NET / Rails
TypeScript 就绪
完整 .d.ts 类型定义,编辑器智能提示
无障碍访问
符合 WCAG AA 标准,键盘导航支持
安装
npm
npm install @kupola/kupola
CDN
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@kupola/kupola/dist/kupola.min.css">
<script src="https://cdn.jsdelivr.net/npm/@kupola/kupola/dist/kupola.min.js"></script>
ESM(现代浏览器)
<script src="https://cdn.jsdelivr.net/npm/@kupola/kupola/dist/kupola.esm.js" type="module"></script>
快速上手
一个完整页面,从零开始使用 Kupola 组件。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@kupola/kupola/dist/kupola.min.css">
</head>
<body data-theme="dark">
<!-- 按钮 -->
<button class="ds-btn ds-btn--primary">主要按钮</button>
<!-- 卡片 -->
<div class="ds-card">
<div class="ds-card__title">欢迎</div>
<div class="ds-card__body">这是你的第一个 Kupola 页面</div>
</div>
<!-- 数据绑定 -->
<input class="ds-input" data-bind="value:name" placeholder="输入姓名">
<span data-bind="text:name"></span>
<script src="https://cdn.jsdelivr.net/npm/@kupola/kupola/dist/kupola.min.js"></script>
</body>
</html>
提示: Kupola 在 DOMContentLoaded 时自动初始化组件,无需手动调用 bootstrap。
组件初始化
通过 data-* 属性声明式初始化,MutationObserver 自动发现动态插入的元素。
<!-- 下拉框:声明 data-dropdown 自动初始化 -->
<div data-dropdown data-value="a">
<div class="ds-dropdown__trigger">选择</div>
<div class="ds-dropdown__menu">
<div data-value="a">选项 A</div>
<div data-value="b">选项 B</div>
</div>
</div>
动态插入后刷新
// CDN / UMD 模式
Kupola.refresh(scopeElement);
Kupola.cleanup(element);
// ESM 模式
import { refresh, cleanup } from 'kupola';
await refresh(scopeElement);
cleanup(element);
数据绑定
基于 Proxy 的响应式双向绑定,DOM 随数据自动更新。
// HTML
<input data-bind="value:username">
<span data-bind="text:username"></span>
// JS
kupolaData.set('username', '张三'); // DOM 自动更新
kupolaData.get('username'); // 读取
kupolaData.load({ username: '...', phone: '...' }); // 批量加载
kupolaData.observe('key', (newVal) => {}); // 监听变化
kupolaData.computed('full', ['first','last'], (f,l) => f + l);
轻量响应式 ref()
import { ref } from 'kupola';
const count = ref(0);
count.value++; // 自动触发所有订阅者
表单验证
内置验证引擎,支持自定义规则,声明式配置。
<form id="myForm">
<input name="email" data-validate="required,email">
<input name="pwd" data-validate="required,min:6">
<button type="submit">提交</button>
</form>
import { KupolaForm } from 'kupola';
const form = new KupolaForm(formElement);
form.getData(); // { email: '...', pwd: '...' }
form.setData(data); // 填充
form.validate(); // 验证所有字段
主题系统
暗色优先,一行切换亮色;11 种中国传统色品牌主题。
<body data-theme="dark"> <!-- 或 "light" -->
import { setTheme, getTheme, setBrand, getBrand, BRAND_OPTIONS } from 'kupola';
setTheme('light');
setBrand('zengqing'); // 曾青 | cui_lv | xionghuang | ...
曾青翠绿雄黄
姜黄蓝绿孔雀蓝
玫瑰紫柿红山茶红
紫云柔蓝
图标系统
80+ SVG 图标,零配置可用。
import { svg, renderIcon, PATHS } from 'kupola';
svg('search'); // 返回 SVG 字符串
renderIcon('bell', el); // 渲染到 DOM 元素
组件速查 — 通用
| 组件 | 导入 | 初始化 |
|---|---|---|
| Button | ds-btn ds-btn--primary | 纯 CSS |
| Card | ds-card | 纯 CSS |
| Tag | import { Tag, initTags } | initTags(root) |
| Badge | ds-badge | 纯 CSS |
| Alert | ds-alert ds-alert--success | 纯 CSS |
| Avatar | ds-avatar | 纯 CSS |
组件速查 — 数据录入
| 组件 | 导入 | 清理 |
|---|---|---|
| Select | import { Select, initSelects } | cleanupSelect(el) |
| Datepicker | import { Datepicker, initDatepickers } | cleanupDatepicker(el) |
| Timepicker | import { Timepicker, initTimepickers } | cleanupTimepicker(el) |
| FileUpload | import { FileUpload, initFileUploads } | cleanupFileUpload(el) |
| ColorPicker | import { ColorPicker, initColorPickers } | cleanupColorPicker(el) |
| Slider | import { Slider, initSliders } | cleanupSlider(el) |
| NumberInput | import { NumberInput, initNumberInputs } | cleanupNumberInput(el) |
| DynamicTags | import { DynamicTags, initDynamicTags } | cleanupDynamicTags(el) |
重要: 每个组件都有对应的
cleanup 函数,页面卸载时必须调用以防内存泄漏。
组件速查 — 数据展示
| 组件 | 导入 | 说明 |
|---|---|---|
| Table | import { KupolaTable, initAllTables } | 排序/分页/筛选/树形/虚拟滚动 |
| Calendar | import { Calendar, initCalendars } | 月/周/日视图 |
| Heatmap | import { Heatmap, initHeatmaps } | 活动热力图 |
| StatCard | import { StatCard, initStatCards } | 统计卡片(数值+趋势) |
| Carousel | import { Carousel, initCarousels } | 图片/内容轮播 |
| ImagePreview | import { showImagePreview } | 图片预览灯箱 |
| VirtualList | import { VirtualList, initVirtualList } | 大数据量虚拟列表 |
Table 示例
const table = new KupolaTable(el, {
columns: [{ key: 'name', title: '名称', sortable: true }],
pagination: true, pageSize: 20,
});
table.setData(data);
table.refresh();
组件速查 — 反馈
| 组件 | 导入 | 用法 |
|---|---|---|
| Modal | import { Modal, createModal, confirmModal } | createModal({ title, content, onConfirm }) |
| Dialog | import { Dialog } | 声明式弹窗 |
| Message | import { message } | message.success('操作成功') |
| Notification | import { notification } | notification({ title, content, type }) |
| Tooltip | import { initTooltip } | 元素 data-title="提示" |
组件速查 — 其他
| 组件 | 导入 | 说明 |
|---|---|---|
| Countdown | import { Countdown, initCountdowns } | 倒计时 |
| SlideCaptcha | import { SlideCaptcha, initSlideCaptchas } | 滑块验证 |
| Web Components | import { registerWebComponents } | 自定义元素桥接 |
声明式数据依赖
useDeps() — 声明式数据获取,自动缓存、重试、刷新。
import { useDeps } from 'kupola';
// 声明数据源
useDeps({
users: {
url: '/api/users',
staleTime: 60000, // 60秒缓存
retry: 3, // 失败重试3次
transform: (data) => data.list // 数据转换
}
});
<!-- HTML 声明式绑定 -->
<div data-deps="users:fetch:/api/users">
<template data-each="users">
<span data-bind="item.name:text"></span>
</template>
</div>
HTTP 客户端插件
可插拔架构,支持 Axios、@navios/http 或任意 HTTP 客户端。
import { configureHttpClient } from 'kupola';
import { createAxiosAdapter } from 'kupola/adapters/axios';
import axios from 'axios';
const api = axios.create({ baseURL: '/api' });
api.interceptors.request.use(config => {
config.headers.Authorization = `Bearer ${getToken()}`;
return config;
});
configureHttpClient(createAxiosAdapter(api));
生命周期
页面级生命周期钩子:beforeMount → mount → afterMount → unmount → destroy
import { createLifecycle } from 'kupola';
const lc = createLifecycle('page:users');
lc.on('mount', () => { /* 初始化组件 */ });
lc.on('unmount', () => { /* 清理资源 */ });
await lc.bootstrap();
await lc.mount();
状态管理
KupolaStore — 轻量级状态管理,支持 state / getters / mutations / actions。
import { createStore } from 'kupola';
const store = createStore('counter', {
state: { count: 0 },
mutations: {
increment(state) { state.count++; }
},
});
store.commit('increment');
国际化
import { t, setLocale, formatDate, formatCurrency } from 'kupola';
setLocale('zh-CN');
t('greeting'); // 翻译 key
formatDate(new Date()); // 2026年7月12日
formatCurrency(99.9, 'CNY'); // ¥99.90
工具库(Tree-Shakable)
命名导出,未使用的工具函数会被 bundler 自动裁剪。
import { stringUtils, arrayUtils, dateUtils, debounce, throttle } from 'kupola';
stringUtils.capitalize('hello'); // 'Hello'
stringUtils.camelize('my-class'); // 'myClass'
arrayUtils.isEmpty([]); // true
dateUtils.formatDate(new Date(), 'yyyy-MM-dd');
debounce(fn, 300);
throttle(fn, 200);
可用命名空间
stringUtils
arrayUtils
objectUtils
numberUtils
dateUtils
validatorUtils
cryptoUtils
preloadUtils
debounce
throttle
后端集成
Kupola 与任何输出 HTML 的后端兼容,三种集成模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 模板渲染 (SSR) | 后端直接输出 HTML | Flask / Django / Jinja2 |
| RESTful API | 前端 data-deps 获取数据 | 任何 REST API |
| 混合模式 | SSR + 局部 API 刷新 | 复杂交互场景 |
详见: INTEGRATION.md — Flask / Django / 静态站点完整集成示例。
TypeScript
完整的 .d.ts 类型定义,开箱即用。
// 自动类型推导
import { KupolaTable, KupolaForm, createStore } from '@kupola/kupola';
// tsconfig.json
{
"compilerOptions": {
"types": ["@kupola/kupola"]
}
}
Tree-Shaking
所有模块均为 ES Module 命名导出,bundler 自动裁剪未使用代码。
// 只导入 Modal + 字符串工具 → 其他 40+ 组件被裁剪
import { Modal, createModal, stringUtils } from '@kupola/kupola';
package.json sideEffects
"sideEffects": ["./js/icons.js", "./js/theme-standalone.js", "*.css"]
构建与发布
构建命令
npm run build # Vite 构建(ESM + CJS + UMD)
npm run build:rollup # Rollup 构建(替代方案)
npm run build:css # 合并 + 压缩 CSS
npm run build:all # CSS + SVG Sprite
产物
| 文件 | 格式 | 用途 |
|---|---|---|
dist/kupola.esm.js | ESM | 现代 bundler |
dist/kupola.cjs.js | CJS | Node.js / 旧 bundler |
dist/kupola.umd.js | UMD | CDN / <script> 标签 |
dist/kupola.min.js | UMD min | 生产环境 CDN |
dist/css/kupola.css | CSS | 完整样式 |
npm 发布
npm publish --access public
当前版本:v1.4.3 | minified ~75 KB gzipped | ESM ~550 KB (unminified) | 362 文件
贡献者: 查看 内部架构文档 — 核心引擎、模块依赖、构建管线、新增组件指南。