JSS JavaScript API 完全指南:实例、StyleSheet 与规则对象的底层原理和实战用法

发布时间:2026/10/10 0:09:54

JSS JavaScript API 完全指南:实例、StyleSheet 与规则对象的底层原理和实战用法 前端UI组件【免费下载链接】jssJSS is an authoring tool for CSS which uses JavaScript as a host language.项目地址https://gitcode.com/gh_mirrors/js/jss点击查看免费下载JSSJavaScript Style Sheets以 JavaScript 作为 CSS 的宿主语言把样式声明写成对象再编译为真实的 CSS 规则。本文以jss包公开的 JavaScript API 为线索系统讲解全局实例与独立实例的创建、setup()配置、StyleSheet 与 Rule 的增删改查、动态函数值更新、类名生成以及服务端渲染聚合等核心能力并结合仓库内 packages/jss/src 的源码实现解释每个 API 背后的真实行为。读完本文你将能够独立搭建 JSS 环境、按需组合插件、控制样式渲染顺序并写出一套可复用的组件样式基础设施。访问全局 JSS 实例jss包默认导出一个全局 Jss 实例绝大多数场景直接引入即可import jss from jss该默认导出由 packages/jss/src/index.js 中的create()创建export default create()也就是说全局实例本质上是create()工厂函数的产物。你不需要手动构造它开箱即用但当你需要隔离配置时可以自己再创建独立实例见下文。快速配置使用默认预设JSS 本身是插件化的推荐通过jss-preset-default一键装配官方推荐插件完成常用语法嵌套、驼峰属性、默认单位、扩展、全局选择器、函数值等的注册import preset from jss-preset-default import jss from jss jss.setup(preset())preset()返回的是一个插件数组jss.setup()内部会把它逐个注册到实例上。完整的安装与使用流程参见 docs/setup.md 和 docs/jss-preset-default.md。创建独立的 JSS 实例jss.create([options])当你要构建一个可复用组件库时组件内部不应依赖宿主项目的 JSS 全局配置——独立实例可以自带一套插件与渲染配置避免与使用方冲突import {create} from jss import camelCase from jss-plugin-camel-case import somePlugin from jss-some-plugin const jss create() jss.use(camelCase(), somePlugin()) jss.createStyleSheet(/* ... */) export default jss注意jss.create(options)与jss.create().setup(options)等价。create只是new Jss(options)的薄封装见 packages/jss/src/utils/createJss.js构造过程中会先注册内部插件再调用setup(options)。深入 jss.setup()实例配置jss.setup(options)setup()是 JSS 实例的核心配置入口可多次调用。支持的全部选项如下选项类型说明createGenerateIdfunction返回一个类名生成器函数的工厂函数用于生成唯一 class 名pluginsfunction[]插件数组会被依次传给jss.use()Rendererclass \| null传null时 JSS 不渲染到 DOM典型场景是服务端渲染也可传入自定义 RendererinsertionPointstring \| DOM Node标记样式表起始位置的 DOM 注释节点字符串或一个已渲染的 DOM 节点该实例产出的样式表会依次插入此点之后idobject传给createGenerateId的选项当前仅含一个布尔属性minify合并语义每次jss.setup()调用都会与旧配置进行浅合并shallow merge唯一例外是plugins——新传入的插件会被追加到已有插件列表而不是覆盖。这一点在 packages/jss/src/Jss.js 的源码中体现得很明确setup(options {}) { if (options.createGenerateId) { this.options.createGenerateId options.createGenerateId } if (options.id) { this.options.id { ...this.options.id, ...options.id } } if (options.createGenerateId || options.id) { this.generateId this.options.createGenerateId(this.options.id) } if (options.insertionPoint ! null) this.options.insertionPoint options.insertionPoint if (Renderer in options) { this.options.Renderer options.Renderer } // eslint-disable-next-line prefer-spread if (options.plugins) this.use.apply(this, options.plugins) return this }从源码还可以看到几个默认值packages/jss/src/Jss.jsid: {minify: false}、Renderer在浏览器环境默认为DomRenderer、在非浏览器环境默认为null。这解释了为何 SSR 场景下不调用任何 DOM API 也能正常工作。insertionPoint的典型用法是在head中放置一个注释节点或直接指定一个已存在的 DOM 元素控制 JSS 样式表相对于第三方样式的渲染位置从而影响 CSS 源顺序优先级。两种写法的完整示例见 docs/setup.md#specify-dom-insertion-pointhead titleJSS/title !-- custom-insertion-point -- /headimport jss from jss jss.setup({insertionPoint: custom-insertion-point})注册插件jss.use()jss.use(plugin)插件通常由工厂函数调用产生如global()use()支持一次注册多个返回实例本身以支持链式调用import global from jss-plugin-global import jss from jss jss.use(global())插件是 JSS 一切高级语法嵌套、全局选择器、函数值、扩展等的来源。源码中use(...plugins)会把每个插件注册进PluginsRegistry见 packages/jss/src/Jss.js。各插件的职责、顺序要求与开发方式参见 docs/plugins.md官方插件仓库内均位于 packages 目录例如 packages/jss-plugin-global。jss.createStyleSheet()创建 Style Sheetjss.createStyleSheet([styles], [options])这是日常使用频率最高的 API。类名默认总是会被生成。可用选项选项默认值说明media无媒体查询会作为style元素的media属性meta无样式表的元信息作为style元素的data-meta属性可传组件名便于调试linkfalse是否将 JSSRule实例与 DOMCSSRule实例链接起来以便动态修改样式开启有一定性能开销element自动创建复用已有的 style 元素否则默认创建新的index0决定 DOM 渲染顺序数值越大优先级越高插入越靠后generateId实例默认生成唯一类名的函数classNamePrefix空字符串追加在类名开头的字符串基本用法import jss from jss const sheet jss .createStyleSheet( { // button 是规则名类名会被自动生成。 button: { width: 100, height: 100 } }, {media: print} ) .attach() console.log(sheet.classes.button) // button-d4f43g渲染结果示意style mediaprint .button-0 { width: 100px; height: 100px; } /style关于index的一个实现细节当你没有显式传入index时packages/jss/src/Jss.js 会以全局sheets注册表当前最高 index 为基准自动递增sheets.index 0 ? 0 : sheets.index 1保证多个 StyleSheet 按创建顺序追加。createStyleSheet返回的 sheet 在构建时会依次走RuleList的add与process流程见 packages/jss/src/StyleSheet.js即所有规则都会经过插件钩子处理后才进入渲染阶段。创建含全局选择器的 Style Sheet若要使用global等全局选择器语法需要先安装并注册 jss-plugin-global 插件其用法见 docs/jss-plugin-global.md。SheetsRegistry服务端渲染的样式聚合SheetsRegistry服务端渲染时你需要把渲染过程中产生的所有样式汇总成一段 CSS 字符串注入 HTML。SheetsRegistry就是干这个的容器——它登记 StyleSheet 并支持一次性字符串化。import jss, {SheetsRegistry} from jss const sheets new SheetsRegistry() const sheet jss.createStyleSheet() sheets.add(sheet) sheets.toString() // 返回全部 Style Sheet 的 CSS 字符串。 sheets.toString({attached: true}) // 仅返回已 attach 的 Style Sheet。 sheets.toString({attached: false}) // 仅返回未 attachdetached的 Style Sheet。 sheets.toString({format: false}) // 返回去除多余空白的紧凑 CSS适合 SSR 场景。toString({attached, format})的两个选项各有用途attached用于浏览器端按挂载状态过滤format默认为true输出带换行的可读 CSS传false时通过getWhitespaceSymbols换成无空白分隔符产出体积更小的紧凑字符串见 packages/jss/src/SheetsRegistry.js。关于 SSR 的更完整链路如何配合JssProvider、如何在每次请求重置状态等参见 docs/ssr.md。SheetsManager按引用计数自动挂载/卸载SheetsManager它统计同一个 Style Sheet 被多少处使用并据此自动attach/detach同时它像 WeakMap 一样允许用任意对象作为 key。React-JSS 正是用theme对象作为 key按主题区分同一组件的样式表。import jss, {SheetsManager} from jss const manager new SheetsManager() console.log(manager.size) // 0 const sheet jss.createStyleSheet() const key {} manager.add(key, sheet) // 登记 sheet重复 key 会被忽略 console.log(manager.size) // 1 manager.get(key) // 返回 sheet // 引用计数 1首次会执行 attach。 manager.manage(key) // sheet // 引用计数 -1减到 0 时自动 detach。 manager.unmanage(key)其实现packages/jss/src/SheetsManager.js内部维护一个WeakMap每个条目记录{sheet, refs}manage时若refs 0则先sheet.attach()再自增unmanage时自减归零则sheet.detach()。若 key 未登记会通过tiny-warning输出警告。StyleSheet 生命周期挂载、卸载与移除挂载sheet.attach()sheet.attach()将 StyleSheet 插入渲染树使其生效。从源码看packages/jss/src/StyleSheet.jsattach()先让 Renderer 挂载 style 元素再把尚未部署的规则一次性写入deploy()内部注释特别强调顺序重要style 元素未挂载到 DOM 时无法使用insertRuleAPI。import jss from jss const sheet jss.createStyleSheet({ button: {color: green} }).attach() // 让样式对布局可见卸载sheet.detach()sheet.detach()卸载暂时用不到的样式表能显著加速后续的 DOM 插入与操作——浏览器需要查找、匹配的 CSS 规则变少了sheet.detach()移除jss.removeStyleSheet(sheet)jss.removeStyleSheet(sheet)同时执行detach()并从全局注册表移除见 packages/jss/src/Jss.jsjss.removeStyleSheet(sheet)控制渲染顺序index 越大越靠后数字更大的index优先级更高在 DOM 中排在更后面从而在源顺序上覆盖前面的规则import jss from jss const sheet1 jss.createStyleSheet({}, {index: 5, meta: sheet-1}).attach() const sheet2 jss.createStyleSheet({}, {index: 1, meta: sheet-2}).attach()style>import jss from jss const sheet jss.createStyleSheet({}) const rule sheet.addRule({ padding: 20, background: blue }) document.body.innerHTML button class${rule.className}Button/button替换规则sheet.replaceRule(nameOrSelector, style, [options])sheet.replaceRule(nameOrSelector, style, [options])与addRule行为一致但若存在同名规则则替换之packages/jss/src/StyleSheet.js。替换时会走RuleList.replace先移除旧规则、再在同位置创建新规则从而保证插件钩子onCreateRule得以重新执行。删除规则sheet.deleteRule(name)sheet.deleteRule(name)要真正把规则从 DOM 中移除创建 StyleSheet 时需开启link: true否则无法拿到对应的renderable。返回true表示规则已从 DOM 删除。对应判断逻辑在 packages/jss/src/StyleSheet.js未找到规则或已挂载但没有rule.renderable时返回false。const sheet jss.createStyleSheet({myButton: {}}, {link: true}).attach() sheet.deleteRule(myButton) // true查询规则sheet.getRule(name)sheet.getRule(name)按名称访问 sheet 内的规则对象import jss from jss const sheet jss.createStyleSheet({myButton: {}}) // 按名称获取。 const rule sheet.getRule(myButton)批量添加sheet.addRules(styles)sheet.addRules(styles)需要分批添加或运行时补规则时使用import jss from jss const sheet jss.createStyleSheet({}) sheet.addRules({ myButton: { float: left }, something: { display: none } })内部实现是循环调用addRule并把成功创建的规则收集成数组返回packages/jss/src/StyleSheet.js。sheet.update()用新数据刷新函数值sheet.update(data)配合 函数值function values语法 使用把所有函数值以data为参数重新求值并在需要时更新对应 CSS 规则底层由 packages/jss/src/RuleList.js 的update/updateOne完成它会对比新旧值只对变化的属性调用rule.prop()并触发onUpdate插件钩子。import jss from jss const styles { container: { height: 200, width: (data) data.width }, button: { color: (data) data.button.color, padding: (data) data.button.padding } } const sheet jss.createStyleSheet(styles, {link: true}).attach() sheet.update({ width: 100, button: { color: red, padding: 20 } })注意这里需要link: true因为函数值运行后要借助 Rule 与 CSSRule 的链接把新值同步到已渲染的 DOM 规则上。脱离 StyleSheet 使用规则jss.createRule([name], style, [options])jss.createRule([name], style, [options])不建 StyleSheet直接对元素应用样式同时仍可使用 JSS 的语法与插件体系packages/jss/src/Jss.js 中标注该方法已标记为 Deprecated将在下一个大版本移除但仍可参考其用法import jss from jss const rule jss.createRule({ padding: 20, background: blue })也可以创建 at-rule 容器规则如mediaimport jss from jss const rule jss.createRule(media, { button: { color: red } })内联应用rule.applyTo(element)rule.applyTo(element)等价于手动逐个设置element.style如element.style.background blue但可以直接复用 sheet 中已定义的规则。它内部调用rule.toJSON()因此受toJSON的能力限制。可运行示例见仓库内 examples/inline。import jss from jss const element document.getElementById(element) jss .createRule({ background: blue }) .applyTo(element)动态读写属性rule.prop(name, [value])rule.prop(name, [value])当link: true且 StyleSheet 已挂载时linker 会保存CSSRule实例的引用因此可以在任意时刻读写规则属性import jss from jss const sheet jss.createStyleSheet( { a: { color: red } }, {link: true} ) // 读取 color。 console.log(sheet.getRule(a).prop(color)) // red // 写入 color。 sheet.getRule(a).prop(color, green)动态修改属性的可视化示例见仓库内 examples/dynamic-props。序列化rule.toJSON()rule.toJSON()返回规则的 JSON 表示。仅支持普通规则不支持嵌套、条件at-rule、keyframes 与 fallback。toJSON()的结果可以稍后用于内联应用rule.applyTo()正是基于它实现的。sheet.toString()导出纯 CSS 字符串sheet.toString()服务端预处理等场景下把 StyleSheet 转为纯 CSS 字符串import jss from jss const sheet jss.createStyleSheet({ button: { float: left } }) console.log(sheet.toString()).button-0 { float: left; }底层由 packages/jss/src/RuleList.js 遍历规则逐个toString()拼接空规则默认会被跳过。配合SheetsRegistry即可完成多 sheet 的聚合输出。createGenerateId 与类名生成策略createGenerateIdsetup({createGenerateId})允许你传入一个工厂函数它返回形如generateId(rule, sheet)的生成器。这种工厂返回函数的设计是为了让 JSS 在需要时重置计数器——例如 packages/react-jss 在服务端渲染时对每个请求重置计数保证类名稳定可预测。默认生成器的实现packages/jss/src/utils/createGenerateId.js要点用计数器保证类名唯一命名构成为classNamePrefix 规则名 moduleId 实例 id 计数器生产环境NODE_ENVproduction下默认输出仅c 规则计数器源码注释说明类名首字符不能是数字因此用c打头以最大化压缩体积。自定义生成器示例import jss from jss const createGenerateId () { let counter 0 return (rule, sheet) pizza--${rule.key}-${counter} } jss.setup({createGenerateId}) const sheet jss.createStyleSheet({ button: { float: left } }) console.log(sheet.toString()).pizza--button-1 { float: left; }压缩选择器minify生产构建中如需进一步压缩类名可在jss.setup中开启minify默认关闭import jss from jss // 给 jss.setup 传入 id 选项并设置 minify 为 true。 jss.setup({id: {minify: true}})getDynamicStyles()抽取动态样式getDynamicStyles(styles)从样式对象中提取出只含函数值属性的子对象。典型场景静态部分在所有元素间共享动态部分按元素单独渲染从而兼顾性能与灵活性。import {getDynamicStyles} from jss const dynamicStyles getDynamicStyles({ button: { fontSize: 12, color: (data) data.color } }) console.log(dynamicStyles) // { // button: { // color: data data.color // } // }实现上packages/jss/src/utils/getDynamicStyles.js会递归遍历对象值为函数的属性被保留值为对象的继续下钻数组与null直接忽略最终返回新对象没有函数值时返回null。插件体系一览JSS 的所有能力都由插件驱动内置插件处理条件规则conditional、keyframes、font-face、viewport 等基础规则类型见 packages/jss/src/plugins外部插件扩展语法与行为。官方插件的安装、使用顺序order matters以及如何编写自定义插件详见 docs/plugins.md仓库内 packages 目录下提供了 camel-case、compose、default-unit、expand、extend、global、isolate、nested、props-sort、rule-value-function、rule-value-observable、template、vendor-prefixer 等官方插件的完整源码与测试。小结围绕jss包的公开 API本文覆盖了从拿一个能用实例到精细控制每个规则生命周期的完整链路create()/setup()/use()负责环境与插件装配createStyleSheet()与attach()/detach()负责样式生产与挂载addRule/replaceRule/deleteRule/update()负责运行期动态调整SheetsRegistry与sheet.toString()打通服务端渲染createGenerateId与getDynamicStyles则提供类名与性能层面的优化手段。结合 packages/jss/src 的源码可以更准确地预判每个 API 在真实环境中的行为边界如insertRule的调试面板差异、deleteRule对link的依赖、setup对 plugins 的追加语义等为封装稳定的组件样式方案打下基础。赞分享前端UI组件【免费下载链接】jssJSS is an authoring tool for CSS which uses JavaScript as a host language.项目地址https://gitcode.com/gh_mirrors/js/jss点击查看免费下载相关推荐Formily Core Query 对象完全指南字段查询 API 的方法签名、底层实现与实战用法Formily Core Query 对象完全指南字段查询 API 的方法签名、底层实现与实战用法 本文围绕 Query.md https://link.gi前端UI组件js-ipfs Bitswap API 完全指南wantlist、unwant 与 stat 的实战用法与底层原理js ipfs Bitswap API 完全指南wantlist、unwant 与 stat 的实战用法与底层原理 本篇技术指南聚焦 js ipfsIPFS存储网络通信Celery 顶层 API 完全指南从 Celery 应用实例到 Canvas 原语与代理对象Celery 顶层 API 完全指南从 Celery 应用实例到 Canvas 原语与代理对象 Celery 是 Python 生态中广泛使用的分布式任务队列任务调度后端消息队列创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/10 3:20:10

WaveDrom编辑器v2.3.2:用文本描述时序图,支持Git版本管理

简介:Wavedrom Editor v2.3.2 Windows 64位版是一款面向FPGA开发者与电子工程师的本地时序图绘制工具,适合需要离线绘图、快速生成信号波形图的用户。它基于简洁的文本语法描述波形,支持上升沿、下降沿、脉冲、注释与颜色标注,并提…

2026/10/10 3:20:10

jxbrowser-7.19 实战:Java 桌面端内嵌 Chromium 浏览器完整指南

简介:这份资源是 jxbrowser-7.19 全系组件包,面向需要在 Java 桌面应用中嵌入浏览器内核的开发者,尤其适合使用 Swing、SWT、JavaFX 等界面框架、希望快速集成 Chromium 渲染能力的中高级工程师。压缩包共 1359 个文件,以 1345 个…

2026/10/10 3:20:10

Flutter CustomPainter在OpenHarmony上做小游戏渲染的实践与优化

最近在做一个小游戏Demo,把Flutter的CustomPainter渲染管线跑在了OpenHarmony设备上,算是把自定义绘制玩明白了。Flutter本身是UI框架,但它的CustomPainter暴露了底层Canvas能力,做轻量级游戏画面渲染完全能胜任,尤其适…

2026/10/10 3:20:10

SpringBoot3多数据源实战:从选型配置到避坑指南

做后端这些年,只要业务稍微复杂一点,“一个应用连一个库”的理想状态基本撑不住。用户数据放用户库、订单数据放订单库、日志又要独立一套,再加上读写分离和多租户隔离的需求,所有问题都指向同一个核心:一个SpringBoot…

2026/10/10 3:15:10

Flutter for OpenHarmony 多语言切换实战:从资源管理到系统适配

做了这么久跨端开发,接到“Flutter for OpenHarmony 教育百科”这种项目时,我第一反应不是技术栈能不能跑通,而是“语言切换”这种看似基础的功能,在鸿蒙生态里到底要趟多少坑。教育百科这个场景很典型:词条多、分类杂…

2026/10/8 10:03:18

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/9 20:15:56

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 0:04:53

从逻辑门到计算机:数字电路核心原理与全加器搭建实战

如果你拆过一台旧电脑的主板,盯着那些黑乎乎的小芯片看上一会儿,可能会冒出同一个疑问:这堆引脚密集的元件,到底是怎么“变”出那么复杂的应用的?答案并不在某个神秘的部件里,而是在所有芯片内部都在反复使…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑