资讯详情

GrapesJS Selector 模型深入解析:CSS 类与 ID 选择器的核心 API 实战指南

📅 2026/9/12 2:35:16 | 华诺云谱 👁 阅读
GrapesJS Selector 模型深入解析:CSS 类与 ID 选择器的核心 API 实战指南
GrapesJS Selector 模型深入解析CSS 类与 ID 选择器的核心 API 实战指南【免费下载链接】grapesjsFree and Open source Web Builder Framework. Next generation tool for building templates without coding项目地址: https://gitcode.com/GitHub_Trending/gr/grapesjs本篇技术指南聚焦 GrapesJS 开源 Web 构建框架中的Selector选择器模型讲解它在 CSS Composer 规则与组件 class 绑定中的核心角色以及toString、getName、getLabel、setActive等完整 API 的用法。读完本文你将掌握如何通过编程方式创建、查询、重命名和状态管理选择器并能够利用 Selector 事件与 Selector Manager 配置构建可定制的样式选择体验。一、Selector 在 GrapesJS 中的定位在 GrapesJS 中Selector 是样式系统的基石实体。它同时服务于两大场景源码注释见 selector_manager/index.tsCSS Composer 中的规则Rules如.btn { color: red }中的.btn组件Components上的 class 集合如button classbtn上的btn。正是这种同一实体、多处复用的设计使得重构与追踪变得容易。例如将同一段 CSS 规则挂到多个组件时只需保证它们共享同一个btnSelector 实例改一处即可全局生效。以官方文档中的经典示例来说明类型划分span #send-btn.btn{ ... }span button idsend-btn classbtn/button /span在这个场景中我们得到三种不同角色的选择器选择器类型说明spantag标签由 HTML 标签名构成send-btnidID类型值为2对应#send-btnbtnclass类类型值为1对应.btn在 Selector 模型内部type仅区分1class与2id两种数值常量定义于 Selector.tsconst TYPE_CLASS 1; const TYPE_ID 2;tag类型并不作为独立的 Selector type 存在而是由解析器在生成 CSS 规则时以字符串形式附加Selector 模型本身专注于 class 与 id。二、Selector 模型属性详解根据 docs/api/selector.md 的 Properties 定义并结合 Selector.ts 中defaults()的实际实现Selector 支持以下属性属性类型默认值说明nameString选择器名称如my-class也是模型的idAttribute见Selector.prototype.idAttribute namelabelString选择器标签展示名如My ClasstypeNumber1选择器类型1class|2idactiveBooleantrue若为false该选择器不可被 Style Manager 选中privateBooleanfalse若为trueStyle Manager 中不可见但仍会渲染到画布和导出代码中protectedBooleanfalse若为true无法从所附加的组件上移除源码中的完整默认值Selector.tsdefaults() { return { name: , label: , type: TYPE_CLASS, active: true, private: false, protected: false, _undo: true, }; }构造时的自动补齐与名称转义Selector构造函数中还有几个值得注意的自动行为Selector.tsname 与 label 互相补齐若只传name则label自动等于name若只传label则name自动取label的值。名称转义escapeName默认策略为name.trim().replace(/\s/g, -)即将名称去首尾空白、把内部空白替换为连字符-也可以通过配置项escapeName注入自定义转义函数。static escapeName(name: string) { return ${name}.trim().replace(/\s/g, -); }三、Selector 实例方法全解析本节逐一讲解 docs/api/selector.md 中定义的 6 个实例方法。3.1 toString()获取选择器字符串将选择器序列化为带前缀的 CSS 字符串。前缀由type决定class 用.id 用#。// Given such selector: { name: my-selector, type: 2 } console.log(selector.toString()); // - #my-selector其底层实现调用getFullName()Selector.ts根据类型拼接前缀getFullName(opts: any {}) { const { escape } opts; const name this.get(name); let pfx ; switch (this.get(type)) { case TYPE_CLASS: pfx .; break; case TYPE_ID: pfx #; break; } return pfx (escape ? escape(name) : name); }3.2 getName()获取选择器名称// Given such selector: { name: my-selector, label: My selector } console.log(selector.getName()); // - my-selector实现为this.get(name) || 始终返回字符串。3.3 getLabel()获取选择器标签// Given such selector: { name: my-selector, label: My selector } console.log(selector.getLabel()); // - My selector3.4 setLabel(label)更新选择器标签// Given such selector: { name: my-selector, label: My selector } selector.setLabel(New Label) console.log(selector.getLabel()); // - New Label实现为this.set(label, label)修改会触发selector:update事件并进入撤销栈_undo: true。3.5 getActive()获取激活状态返回布尔值!!this.get(active)。非激活active: false的选择器不能被 Style Manager 作为可样式化目标选中。3.6 setActive(value)更新激活状态selector.setActive(false); // 从 Style Manager 候选列表中隐藏 selector.setActive(true); // 重新启用附isId() / isClass() 便捷判断源码还提供了两个类型判断方法Selector.tsisId() { return this.get(type) TYPE_ID; } isClass() { return this.get(type) TYPE_CLASS; }四、Selector 集合与 Selector Manager 的关系单独的 Selector 通常由Selector Manager 模块editor.Selectors管理其概念说明见 docs/api/selector_manager.md。初始化时通过配置对象注入const editor grapesjs.init({ selectorManager: { // options } });实例化后通过 API 获取模块const sm editor.Selectors;Selector Manager 内部维护两类集合index.tsall全量选择器仓库Selectors集合以name_type作为唯一模型 id见 Selectors.ts 的modelIdselected当前选中的选择器集合。4.1 添加add()const selector selectorManager.add({ name: my-class, label: My class }); console.log(selector.toString()) // .my-class // 等价写法直接传字符串标识 const selector selectorManager.add(.my-class); console.log(selector.toString()) // .my-classadd()的底层addSelector()会做两件关键事index.ts字符串标识归一化以#开头视为 id自动剥离前缀并设置type: 2以.开头视为 class剥离前缀去重若all集合中已存在同名同类型选择器直接返回既有实例不会重复创建——这正是同一 class 实体、多处共享的实现保证。4.2 查询get()const selector selectorManager.get(.my-class); // 获取 Id const selectorId selectorManager.get(#my-id);get()同样支持#/.前缀解析并支持传入数组批量查询去重后返回数组。4.3 移除remove()const removed selectorManager.remove(.myclass); // 或直接传 Selector 实例 selectorManager.remove(selectorManager.get(.myclass));返回被移除的 Selector。注意protected为true的选择器在从组件移除时会被拦截见下方removeSelected。4.4 重命名rename()const selector selectorManager.get(myclass); const result selectorManager.rename(selector, myclass2); console.log(result selector ? Selector updated : Selector with this name exists already);rename()会先对新名称做转义若新名称已存在则直接返回既有选择器而不覆盖index.tsrename(selector: Selector, name: string, opts?: SetOptions) { const newName this.escapeName(name); const result this.get(newName); return result || selector.set({ name: newName, label: name }, opts); }4.5 全量获取getAll()const allSelectors selectorManager.getAll(); // Selectors 集合 const selectorArray selectorManager.getAll({ array: true }); // Selector[]4.6 与选中组件联动getSelected / addSelected / removeSelectedgetSelected()返回所有选中组件共有的选择器基于各组件getSelectors().getValid()取交集实现见__commongetSelectedAll()返回当前选中集合的全部选择器不分是否共有addSelected(.new-class)把新选择器附加到所有选中的组件removeSelected(.myclass)从所有选中组件移除该选择器protected的选择器会被跳过index.tsremoveSelected(selector: Selector) { this.em.getSelectedAll().forEach((trg) { !selector.get(protected) trg trg.getSelectors().remove(selector); }); }getSelectedTargets()返回当前参与样式编辑的目标数组组件或 CssRule取决于componentFirst配置例如const targetsToStyle selectorManager.getSelectedTargets(); console.log(targetsToStyle.map(target target.getSelectorsString()))4.7 componentFirst 模式setComponentFirst / getComponentFirstselectorManager.setComponentFirst(true); console.log(selectorManager.getComponentFirst()); // true当componentFirst开启时所有样式变更将直接作用于选中组件生成 ID 规则而非作用于共享的 class 选择器——后者会改动所有使用同一 class 的组件可能造成画布可视区域之外的非预期样式变化配置说明见 config.ts。默认值为false。五、Selector 事件系统Selector Manager 定义了一套完整事件枚举见 types.ts文档与源码完全一致事件名触发时机回调参数selector:add选择器被添加Selectorselector:remove选择器被移除Selectorselector:remove:before移除前一刻Selectorselector:update选择器属性更新Selector, changes 对象selector:state状态state变化事件数据对象selector:custom自定义选择器事件{ states, selected, container }selector上述所有事件的统一入口聚合事件数据对象用法示例editor.on(selector:add, (selector) { ... }); editor.on(selector:remove, (selector) { ... }); editor.on(selector:remove:before, (selector) { ... }); editor.on(selector:update, (selector, changes) { ... }); editor.on(selector:state, (state) { ... }); editor.on(selector:custom, ({ states, selected, container }) { ... }); // 捕获所有选择器事件的统一入口 editor.on(selector, ({ event, selector, changes, ... }) { ... });从源码看selector:custom事件数据由__customData()生成index.ts包含states全部状态、selected选中选择器与container渲染容器是构建完全自定义 Selector Manager UI 的关键钩子。此外还有内部事件selector:type组件优先模式切换时触发。六、States 状态选择器的伪类维度Selector Manager 的setState/getState/getStates/setStates用于管理状态State即 CSS 伪类如:hover、:active。6.1 State 模型State 是独立于 Selector 的轻量模型State.ts仅含两个属性name状态名如hover、nth-of-type(2n)label展示标签如Hover、Even/Odd未提供时getLabel()回退返回name。6.2 状态 APIselectorManager.setState(hover); // 切换当前状态 selectorManager.getState(); // 读取当前状态值 const states selectorManager.setStates([ { name: hover, label: Hover }, { name: nth-of-type(2n), label: Even/Odd } ]); // 返回新的 State 数组setState()实际调用em.setState(value)状态变化会触发selector:state事件setStates()通过states.reset(...)整体替换状态集合index.ts。默认状态集定义于 config.tsstates: [{ name: hover }, { name: active }, { name: nth-of-type(2n) }]七、Selector Manager 完整配置项在grapesjs.init({ selectorManager: {...} })中可用的全部配置项源码注释见 config.ts配置项类型默认值说明stylePrefixStringclm-样式前缀受全局pStylePrefix影响appendToString | HTMLElement渲染容器为空则不渲染 UIselectorsArray[]默认选择器集合statesArray[{ name: hover }, { name: active }, { name: nth-of-type(2n) }]默认状态escapeNameFunction内置转义自定义选择器名称转义策略selectedNameFunction—自定义Selected提示文案生成策略iconAdd/iconSync/iconTagOn/iconTagOff/iconTagRemoveString(SVG)内置 SVG各 UI 图标renderFunction—完全自定义 Selector Manager 渲染componentFirstBooleanfalse组件优先模式见 4.7customBooleanfalse为true时跳过默认 Selector Manager UI 渲染自定义转义与自定义渲染示例const editor grapesjs.init({ selectorManager: { // 例如把名称中的空格替换为下划线 escapeName: name name.replace( , _), // 自定义Selected提示 selectedName: ({ result, state, target }) ${result} - ID: ${target.getId()}, } });render配置项允许返回一段 HTML 字符串重排整个界面并可通过data-*属性让模块识别关键元素data-states状态下拉容器、data-selectors选择器列表容器、data-input新增输入框、data-add新增触发元素、data-sync-style样式同步按钮需开启componentFirst、data-selected选中结果展示区。同时会注入labelHead、labelStates、labelInfo等本地化文案供模板使用。八、实战组合Selector CssRule 完整链路选择器最终要落到 CSS 规则上才能产生样式。结合 docs/api/css_rule.md一个典型的编程式工作流如下// 1. 添加/复用选择器 const myClass editor.Selectors.add(.my-class); // 2. 通过 CSS Composer 创建规则并设置样式 const rule editor.Css.setRule(.my-class, { color: red }); // 3. 规则中可携带状态与媒体查询 const hoverRule editor.Css.setRule(.my-class:hover, { color: blue }); hoverRule.selectorsToString(); // .my-class:hover hoverRule.selectorsToString({ skipState: true }); // .my-class hoverRule.getDeclaration(); // .my-class:hover{color:blue;}整个过程同样会走selector:add、selector:update等事件方便统计与联动。若组件附加了同一my-class选择器Style Manager 中修改样式时会自动命中该共享规则体现选择器即实体的核心设计。九、测试验证与进一步阅读仓库中对应的测试用例可以进一步验证上述 API 行为Selector 模型测试test/specs/selector_manager/model/SelectorModels.tsClass 标签视图测试test/specs/selector_manager/view/ClassTagsView.ts选择器管理器端到端测试test/specs/selector_manager/e2e/ClassManager.ts需要继续深入的相关 API 文档Selector Manager 模块文档模块级方法、事件与配置总览State 文档状态模型属性与getName/getLabelCssRule 文档选择器在规则中的具体应用CSS Composer 模块文档CSS 规则的整体管理Style Manager 模块文档选择器如何参与样式面板渲染【免费下载链接】grapesjsFree and Open source Web Builder Framework. Next generation tool for building templates without coding项目地址: https://gitcode.com/GitHub_Trending/gr/grapesjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。