序言
我们已经领略了 BEM 规范在 CSS 样式管理方面的强大功能🌌,它为我们的样式代码带来了秩序与高效。但在前端开发中,JavaScript 作为交互逻辑的核心语言,与 CSS 紧密协作🤝。那么,如何让 BEM 规范在 JavaScript 中发挥作用,实现更高效的代码编写和维护呢🧐?这正是我们即将深入探讨的内容。在接下来的篇章里,我们将逐步揭开 JavaScript 实现 BEM 规范的神秘面纱,为你的前端开发技能库增添重要的一环💪。
举例
深入探究 BEM 规范在 CSS 领域的卓越效能后,我们已然明晰块(Block)、元素(Element)、修饰符(Modifier)是如何彼此协同,构建起一套条理清晰、结构化的样式管理体系的。然而,在前端开发的广阔版图中,当我们将视角聚焦于组件开发时,一个至关重要的要素 —— 状态(State),如同夜空中一颗悄然升起的新星🌟,逐渐进入我们的视野。它与 BEM 规范深度融合、相互交织,共同为组件赋予了更为丰富的交互性与动态表现力。
以我们日常开发中频繁使用的 Button 组件为例,它看似简约,实则暗藏诸多精巧设计。请瞧下面这段 HTML 代码:
<button class="button button--primary is-disabled">
<i class="button__icon"></i>
<span class="button__text">提交</span>
</button>
在这段代码里,button
作为 Button 组件的块,奠定了组件的基本结构与核心功能🏗️,任何对按钮的通用样式设定与基础交互逻辑,都围绕这个块展开。button__icon
无疑是 Button 组件的图标元素。而button--primary
则是 Button 组件的修饰符,用于改变按钮的外观风格,彰显出特定的样式特征👗。至于is-disabled
,它代表了 Button 组件的状态,表明该按钮当前处于禁用状态🚫。
有了上述对 Button 组件基于 BEM 规范与状态的清晰认知,我们在 JavaScript 中实现相关功能的思路也逐渐清晰起来。
实现
市面上的组件库都有自己独特的命名空间,就像 element 组件库,它的组件都是以el-
开头的。为了让我们的组件在代码之林中也能拥有清晰的标识,自然也要打造自己专属的命名空间🚩。
我们在packages/hooks/use-namespace
目录下新增index.ts
文件,开启构建我们的 BEM 命名空间之旅。
export const defaultNamespace = 'n'
const statePrefix = 'is-'
const _bem = (
namespace: string,
block: string,
blockSuffix: string,
element: string,
modifier: string
) => {
let cls = `${namespace}-${block}`
if (blockSuffix) {
cls += `-${blockSuffix}`
}
if (element) {
cls += `__${element}`
}
if (modifier) {
cls += `--${modifier}`
}
return cls
}
export const useNamespace = (block: string) => {
const namespace = defaultNamespace
const b = (blockSuffix = '') => _bem(namespace, block, blockSuffix, '', '')
const e = (element?: string) => (element ? _bem(namespace, block, '', element, '') : '')
const m = (modifier?: string) => (modifier ? _bem(namespace, block, '', '', modifier) : '')
const be = (blockSuffix?: string, element?: string) =>
blockSuffix && element ? _bem(namespace, block, blockSuffix, element, '') : ''
const bm = (blockSuffix?: string, modifier?: string) =>
blockSuffix && modifier ? _bem(namespace, block, blockSuffix, '', modifier) : ''
const em = (element?: string, modifier?: string) =>
element && modifier ? _bem(namespace, block, '', element, modifier) : ''
const bem = (blockSuffix?: string, element?: string, modifier?: string) =>
blockSuffix && element && modifier ? _bem(namespace, block, blockSuffix, element, modifier) : ''
const is = (name: string, state: boolean | undefined = true) =>
state ? `${statePrefix}${name}` : ''
return {
namespace,
b,
e,
m,
be,
bm,
em,
bem,
is,
}
}
在这段代码中,我们定义了一个默认的命名空间n
,并通过一系列函数来生成符合 BEM 规范的类名。这些函数就像是一个个精巧的工匠🧑🔧,根据我们传入的块、元素、修饰符和状态等信息,打造出独一无二的类名标识,让我们在 JavaScript 中能够轻松地与遵循 BEM 规范的组件进行交互,为前端开发带来更多的便利与可能。
🦀🦀感谢看官看到这里,如果觉得文章不错的话🙌,点个关注不迷路⭐。
诚邀您加入我的微信技术交流群🎉,群里都是志同道合的开发者👨💻,大家能一起交流分享摸鱼🐟。期待与您在群里相见🚀,咱们携手在开发路上共同进步✨ !
👉点我
感谢各位大侠一路相伴,实在感激! 不瞒您说,在下还有几个开源项目 📦,它们就像精心培育的幼苗 🌱,急需您的浇灌。要是您瞧着还不错,麻烦动动手指,给它们点亮几颗 Star ⭐,您的支持就是它们成长的最大动力,在此谢过各位大侠啦!
Nova UI
组件库:https://github.com/gmingchen/nova-ui- 基于 Vue3 + Element-plus 管理后台基础功能框架
- 预览:https://admin.gumingchen.icu
- 基于 Vue3 + Element-plus + websocket 即时聊天系统
- 基于 node 开发的后端服务:https://github.com/gmingchen/node-server