本仓库的目标是做一套可用于生产环境的 JS + CSS 框架,最终在业务项目中只需要引入:
xjs.js(单文件 JS)xjs.css(单文件 CSS)但在本仓库内,为了保持可维护性,开发源码仍然分散在多个文件中(例如 animal.js、layer.js),再通过构建脚本合并为单文件产物。
本文档用于统一后续完善/开发的目录约定、命名规范、编码习惯、测试方式、发布流程。请把它当成项目的“团队约定”。
当前结构(关键文件):
animal.js:动画/选择器核心(Selection / animate / svg / timeline / scroll / inView 等能力)layer.js:弹出层组件(UI + 交互逻辑)xjs.css:库运行时需要的所有 UI 样式(例如 Layer 的 .layer-*)xjs.js:
animal.js + layer.js)dist/xjs.js:生产合并产物(由构建命令生成)doc/index.html:统一测试/文档入口(支持点击导航直接进入示例页面)main.go:构建与本地静态服务脚本animal.js / layer.js / xjs.css / doc/**dist/xjs.js(以及任何由构建生成的合并文件)dist/xjs.js + xjs.css 为准仓库自带 Go 静态服务(默认端口 8080):
go run main.go serve
然后在浏览器打开:
http://localhost:8080/doc/index.html说明:
doc/index.html会作为“测试总控台”,左侧导航/中间列表/右侧 iframe 组合用于快速打开各类测试页面。
将 animal.js + layer.js 合并输出到 dist/xjs.js:
go run main.go build
或指定输出路径:
go run main.go build path/to/xjs.js
对外承诺以下全局变量:
window.$:主入口(jQuery 风格选择器 + 链式能力)window.xjs:兼容别名(与 $ 等价)window.animal:兼容别名(与 $ 等价)window.Layer:Layer 构造/工厂入口$(selector) 返回的 Selection 链式对象进入$.config(xjs/animal 为别名)Promise(例如 animate().then(...))Selection 以支持链式调用(例如 .layer(...).addClass(... ) 未来扩展)animal.js、layer.js,新增模块保持一致)animal.js:核心选择器与动画体系(不直接引入 UI 样式)layer.js:UI 组件(允许依赖 xjs.css)camelCasePascalCaseUPPER_SNAKE_CASE_fire、_onKeydown)$(selector) 返回 Selection(继承 Array 的可链式集合)animate / draw / inViewAnimate / layer / unlayerparams.options(现有实现已倾向此策略)xjs.css)xjs.css<style>(可接受“确保已引入 CSS”的兜底逻辑,但不把完整样式写入 JS)目前 Layer 使用 .layer-*,后续新增组件建议遵循:
x-<component>-* 或沿用当前 layer-*(但需保持一致)xjs-,则逐步迁移)目标是:业务 CSS 不会因为类名冲突而被库“意外影响”,也不会轻易覆盖库样式。
新增 UI 组件时,尽量通过 CSS 变量暴露可定制项:
--xjs-color-primary--xjs-radius-md--xjs-shadow-lg--layer-...(若继续沿用 layer 命名空间)并保证:
doc/)doc/index.html 进入doc/layer/、doc/svg/、doc/tween_*)doc/index.html 的导航树中挂入口,保证“可点击直达”目标:我只说“改哪个功能的演示”,你能精准找到对应页面、路由和引用的库。
/doc/#<token> → 映射到 doc/<path>.html
/doc/#layer_test__dom__steps → doc/layer/test_dom_steps.html...、伪代码或省略写法(如隐藏 DOM 块也要完整展示)doc/demo.css(示例通用样式)、xjs.css(组件运行时样式)doc/highlight_css.js(代码高亮)animal.js + layer.js(调试时直接加载源码,避免缓存覆盖)落地示例(当前对照页):
/doc/#layer_test__dom__stepsdoc/layer/test_dom_steps.htmlanimal.js)典型落点:
Selection.prototype.xxx = function (...) { ... }Selection 类体内增加方法(更推荐,保持结构统一)$.xxx = ...(xjs/animal 为别名)推荐方式:
component_xxx.js(或未来统一 components/xxx.js)xjs.css 增加 xxx-*(或 xjs-xxx-*)样式main.go build() 的拼接顺序)当前
main.go固定合并animal.js + layer.js,当模块增长时建议升级为“配置式列表”。
每次准备对外发布(或业务项目更新版本)前建议走一遍:
doc/index.html,对本次变更相关页面逐个验证go run main.go builddist/xjs.js 更新(不要手改)xjs/animal/Layer 是否都存在$ 是否仍然是“显式开关才导出”xjs.css 的类名是否避免与业务冲突当模块越来越多时,建议逐步引入以下工程化能力(仍保持“最终只发两个文件”的目标):
src/animal/、src/layer/、src/core/main.go 从“硬编码拼接两个文件”升级为“按清单拼接多个文件”dist/xjs.js 注入版本号、构建时间、变更摘要(便于定位线上问题)如果本文档与源码现状出现不一致:
$(同时保留 xjs/animal 兼容别名)Layer.run(options) / Layer(options)Layer.$(baseOptions).step(...).run()Layer.flow(steps, baseOptions)示例(最简弹窗):
Layer.run({
title: 'Hello',
text: 'Triggered by click',
showCancelButton: true
});
title / text(纯文本)html(innerHTML)dom(推荐):'#selector' | Element | <template>content(兼容):'#selector' | Element | { dom, selector, mode, clone }domMode:'move'(默认,关闭时还原)/ 'clone'(克隆展示)confirmButtonText / cancelButtonText / showCancelButtoncloseOnClickOutside / closeOnEscpopupAnimation(弹窗进入)/ iconAnimation(图标动效)icon(内置类型或 svg:Name)/ iconSize / iconLoop(Lottie)background: 'svg(...)' | 'url(...)' | 'css(...)'width / height(数字默认 px;字符串任意单位)
iwidth / iheight:图标容器 .layer-icon 尺寸(可覆盖 CSS 默认值)theme: 'auto' | 'light' | 'dark'
auto 跟随 prefers-color-scheme(暗色环境自动用浅色文字)light 强制浅色文字(适合深色背景)dark 强制深色文字(适合浅色背景)replace: true(替换当前已存在弹窗)preConfirm(popup):返回 false 阻止关闭/下一步;可返回值或 Promise。didOpen(popup) / willClose(popup) / didClose():生命周期回调。isConfirmed / isDismissedvalue:非 steps 为单值;steps 为数组data:steps 容器模式下自动汇总表单数据// 直接移动 DOM(默认)
Layer.run({ title: 'Edit', dom: '#my_form', showCancelButton: true });
// 以 clone 方式展示
Layer.run({ title: 'Preview', dom: '#my_form', domMode: 'clone' });
Layer.$(base).step(step1).step(step2).run()Layer.flow([step1, step2], base){ step: '#container', stepItem: '.item' }nextIcon / prevIcondata-step-title:步骤标题data-step-background:背景(支持 svg(...) / url(...) / css(...))data-step-icon:图标(支持 svg:<name>)data-step-width / data-step-height:弹窗尺寸data-step-iwidth / data-step-iheight:图标容器尺寸data-step-theme:auto | light | dark示例(链式 steps):
Layer.$({ icon: 'info', closeOnEsc: false })
.step({ title: 'Step 1', dom: '#step1', showCancelButton: true })
.step({ title: 'Step 2', dom: '#step2' })
.run()
.then((res) => {
if (res.isConfirmed) console.log(res.value);
});