【问题标题】:Achieving true separation of concerns between HTML, CSS & JS?在 HTML、CSS 和 JS 之间实现真正的关注点分离?
【发布时间】:2016-09-19 11:59:23
【问题描述】:

使用以下 HTML 结构,如何最好地实现 HTML、CSS 和 JS 之间的关注点分离?

<nav role="navigation" class="site-nav js-site-nav">
  <ul class="site-nav__list">
    <li class="site-nav__item"><a href="#" class="site-nav__link">Menu Item 1</a></li>
    <li class="site-nav__item"><a href="#" class="site-nav__link is-active">Menu Item 2</a></li>
  </ul>
</nav>

演示: http://codepen.io/achisholm/pen/wGVGxj

首先,这个例子似乎并没有真正解耦。我发现类命名系统不适合分开。在尝试定位链接时,我仍然需要在 JS 中的某处使用 .site-nav__link 选择器。

在每个链接上使用 JS 钩子类似乎是向右移动 方向。在每个链接上添加 .js-site-nav__link 类是 改进?

<nav role="navigation" class="site-nav">
  <ul class="site-nav__list">
    <li class="site-nav__item js-site-nav__item"><a href="#" class="site-nav__link">Menu Item 1</a></li>
    <li class="site-nav__item js-site-nav__item"><a href="#" class="site-nav__link is-active">Menu Item 2</a></li>
  </ul>
</nav>

这对我没有太大吸引力,因为虽然与演示类没有本质上的联系,但使用整个 BEM 名称仍然很难进行任何结构更改,而且我认为仅使用 .site-nav__link 并没有什么好处.

我可能会考虑像js-link 这样的类名,但泛化会导致其他问题。定位 .js-site-nav .js-link 是否会给我最好的一切?

<nav role="navigation" class="site-nav">
  <ul class="site-nav__list">
    <li class="site-nav__item js-link"><a href="#" class="site-nav__link">Menu Item 1</a></li>
    <li class="site-nav__item js-link"><a href="#" class="site-nav__link is-active">Menu Item 2</a></li>
  </ul>
</nav>

我觉得这真的是解耦了,但它是否达到预期效果?

感谢@claudios 提供了一个简单的例子,它有一个很好的 JS 钩子,js-add 其中包括一个有帮助的动词。像这样的东西效果很好,但在我的例子中不合适。感觉像js-toggle-link 这样的 JS 钩子可能会开始变得结构良好。

来源:HTML 摘自以下演讲(在 17 分钟后跳转到相关部分)... https://vimeo.com/album/3953264/video/166790749#t=17m0s

【问题讨论】:

  • “这个例子似乎并没有真正解耦” 需要我们观看视频来了解您的问题。问题需要自成一体。为了让我们理解,您需要逐条列举问题本身并定义您的期望。使用前缀类很常见
  • 对造成的混乱表示歉意。这是关于我稍后在问题和提供的 Codepen 中包含的 HTML 示例
  • 再一次...问题应该是自包含的,外部链接仅用于支持问题中的实际内容。我们不必离开现场来全面审查您遇到的问题。在我们阅读并理解完整问题后,沙盒中的演示很有帮助
  • 我已编辑问题,以便将视频作为脚注提供。我将尝试将问题重新表述得更简洁。
  • 我看到了解耦的优点(虽然在很多情况下它是多余的并且超出了目标),但我更喜欢仅将类用于样式,并将钩子放在属性(数据或自定义)。

标签: javascript jquery html css bem


【解决方案1】:

据我了解,您想要一种解耦 html、css 和 javascript 的好方法。根据我的经验,我建议对所有 js 使用前缀。

例如:js-*

想象一下,如果你有一个像&lt;button class="add"&gt;Add&lt;/button&gt; 这样的按钮,然后你想在上面放一个js,那么可以重写为。

<button class="js-add add">Add</button>

现在,如果这个按钮更特别,并且需要与具有add 类的所有按钮不同,那么您可以编写

<button class="js-add add-special">Add</button>

希望这会有所帮助。

【讨论】:

  • 这很好地说明了这个想法。在您的示例中,它看起来和感觉都是正确的。带有诸如js-addjs-save 之类的动词的js 钩子的类名将很好地放在诸如(以我的示例)site-nav__link 之类的表示类名旁边,但是在我的示例中,导航链接的最佳类名是什么?我的建议是js-linkjs-toggle 或类似的东西怎么样?
【解决方案2】:

在我看来,使用这样的命名只会使事情变得复杂,而现在您可以使用CSS 中的SASSJS 中的OOP 编码并在正确的层次结构中选择元素,从而轻松地组织您的元素和事件。

您必须尽可能简单地命名您的元素和事件。

让我详细说明:

假设我们想要实现一个像你给出的例子一样的结构:

<nav role="navigation" class="site-nav js-site-nav">
  <ul class="site-nav__list">
    <li class="site-nav__item"><a href="#" class="site-nav__link">Menu Item 1</a></li>
    <li class="site-nav__item"><a href="#" class="site-nav__link is-active">Menu Item 2</a></li>
  </ul>
</nav>

虽然在这个层次结构中命名你的元素真的很整洁,但一段时间后它会变得有点混乱,而且如果有人新加入项目并看到命名,好吧,让我们说它会接受他们有一段时间自己记住这些名字(而不是从其他代码中作弊)。

如果我要实现这个结构,它会是这样的:

HTML

<nav role="navigation" class="site-nav js">
  <ul>
    <li><a href="#">Menu Item 1</a></li>
    <li><a href="#" class="active">Menu Item 2</a></li>
  </ul>
</nav>

SCSS

.site-nav{
    //styling here

    &.js{
    //styling here
    }

    ul{
        //styling here

        li{
            //styling here

            a{
               //styling here
            }
        }
    }
}

现在假设我想为以前称为a.site-nav__linka 写一个事件:

JS

document.querySelector('.site-nav ul li a').addEventListener(eventName, function() {});

层次结构让您尽可能轻松地找到元素,并且您永远不会忘记这些元素的名称。

现在让我们来看看.js,我们为什么要使用它?

一般来说,您不需要为js 中使用的每个元素都使用“js 类”,那么我们为什么要使用它呢?让我用一个例子来解释一下。

假设我们有一个名为 .button 的按钮,其中包含一些样式。

SCSS

.button{
    //Some styles
}

我们希望这些按钮中的一些(具有相同的样式)在被点击后变大,因此我们为它们添加了一个.js 类以知道它们正在被@987654336 操作@ 并更轻松地处理它们。

document.querySelector('.button.js').addEventListener('click', function() {
    this.className+=' clicked';
});

CSS 中我们写道:

.button{
    //Some styles
    &.js{
        .clicked{
            transform:scale(1.1);
        }
    }
}

就是这么简单!

另一方面,如果我们不想使用 .js 类(它也可以用于其他元素,因为我们从不单独使用它,而且它总是带有另一个类或 id作为.active) 我们必须为这些按钮编写另一个类,但是通过一点层次结构,我们可以编写更少的代码保持井井有条而且我们永远不必作弊来自其他脚本,因为元素和事件的名称太难记住了!

【讨论】:

  • 我不建议 OP 放弃 BEM - 虽然他的示例很简单,但在大型项目中非常方便
  • 同意,但这并不简单,BEM 也会让大型项目在一段时间后变得有些混乱,特别是对于新手。
  • 如果替代方案是:让我们允许每个 CSS 人员以任何他们想要的方式命名他们的类,所以,在一个项目中有类似 class='my-class myClass blue_button' 的东西,那么我很高兴更喜欢 BEM
  • 我从来没有说过每个人都可以随心所欲地命名类,我只是说它需要尽可能简单,这意味着每个人都需要使用类.active来显示类的活跃度以元素为例。所以my-class 总是my-class,我们通过文档中的层次结构来区分这些my-class 元素,而不是通过使用这些名称.your-element__the-parent--my-class,这在一个长期的项目
  • 我发现 BEM 是大规模前端架构的必要之恶。我不喜欢它,但它有效。我认为在没有基于 BEM 的类的情况下也可以提出同样的问题
【解决方案3】:

实际上 BEM 是相反的想法。

从了解自身一切的块(组件)的角度来思考:标记 (HTML)、视图 (CSS) 和行为 (JS)。

因此,BEM 认为应该将它们放在一起,而不是将这三者分开。

回到site-nav 的示例,您可能会将所有 JS 委托给块本身,并像使用块的内部 API 一样使用其元素进行操作(is-active 应该成为 site-nav__link 的修饰符)。

请查看 bem.info 上的文档以了解更多信息:https://en.bem.info/methodology/js/

【讨论】:

  • 我曾经使用过您过去建议的方法,但由于它没有提供我希望的灵活性,因此不再使用它。如果不更改 JavaScript 中的选择器,我们就无法修改我们的 scss。将 JS 绑定到用于表示的同一个类是脆弱的,并且很难更改或重用。关注点分离是一个关于维护的原则。我建议观看我在原始帖子中发布的整个演讲。我想你会喜欢的。或者为了进一步阅读,这个:philipwalton.com/articles/decoupling-html-css-and-javascript
  • 在很多情况下,您应该将不同的实体彼此分开,但我同意@tadatuta 关于原始 BEM 的想法。 upd:顺便说一句,在您当前的情况下,js-link 看起来像一个单独的块,应该与 site-nav__link 混合。取决于您在这些实体中的语义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-13
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 1970-01-01
相关资源
最近更新 更多