Web应用不尽然如何影响其它代码?栏有子菜单怎么做?
,上面的规则就无法生效,然而他也不清楚其中缘由。
只要你网站的标记很少改动,CSS Zen Garden就是一个非常不错的主意。但是这和当今的Web应用不尽然都是这种情况。与冗长而又复杂的CSS选择器相比,最好的办法是在可视化组件本身的根元素增加一个或多个类选择器。比如,如果侧边栏有子菜单,只需要为每个子菜单元素增加submenu类选择器,而不要用这样的形式:
ul.sidebar > li > ul {
/ submenu styles /
}
这种方式的结果是在HTML中需要更多的类选择器,但从长远来看,这又降低了耦合度,以及让代码更可重用和可维护,并且还能让你的标记自文档化。如果HTML里没有类选择器,那些对CSS不熟悉的开发者就不清楚HTML的改动如何影响了其它代码。另一方面,在HTML中使用类选择器能很清晰地看到那些样式或者功能被使用到了。
多个类选择器的职责
一个类选择器往往是用来同时作为样式和JavaScript的钩子。虽然这看起来似乎很节约(因为至少减少了一个类标记),但事实上,这是把元素的表现和功能耦合起来了。
class="add-item">Add to Cart
以上例子描述了一个带有add-item类样式的”添加到购物车”按钮。
如果开发者想为此元素添加一个单击事件监听器,用已经存在的类选择器作为钩子非常的容易。我的意思是,既然已经存在了一个,为何要添加另一个呢? 但是想想看,有很多像这样的按钮,遍布了整个网站,都调用了相同的JavaScript功能。再想想看,如果市场团队想要其中一个和其它看起来完全不同但功能相同的按钮呢。也许这样就需要更多显著的色彩了。
问题就来了,因为监听单击事件的JavaScript代码希望add-item类选择器被使用到,但是你新的按钮又无法使用这个样式(或者它必须清除所有声明的,然后再重置新的样式)。还有,如果你测试的代码同时也希望使用add-item类选择器,那么你不得不要去更新那么代码用到的地方。更糟糕的是,如果这个”添加到购物车”功能不仅仅是当前应用用到的话,也就是说,把这份代码抽象出来作为一个独立的模块js选择器,那么即使一个简单的样式修改,可能会在完全不同的应用中引发问题。
使用javaScript钩子最好的(事实上也是比较鼓励的)做法是,如果你需要这么做,使用一种方式来避免样式和行为类选择器之间的耦合。
我的个人建议是让JavaScript钩子使用前缀,比如:js-*。这样的话,当开发者在HTML源代码中看到这样的类选择器,他就完全明白个中原因了。所以,上述的”添加到购物车”的例子可以重写成这样:
class="js-add-to-cart add-item">Add to Cart
现在,如果需要一个看起来不同的按钮,你可以很简单地修改下样式类选择器,而不管行为的类选择器。
class="js-add-to-cart add-item-special">Add to Cart
JavaScript更多的样式操作
JavaScript能用类选择器去DOM中查找元素,同样,它也能通过增加或移除类选择器来改变元素的样式。但如果这些类选择器和当初加载页面时不同的话也会有问题。当JavaScript代码使用太多的组成样式操作时,那些CSS开发者就会轻易去改变样式表,却不知道破坏了关键功能。也并不是说,JavaScript不应该在用户交互之后改变可视化组件的外观,而是如果这么做,就应该使用一种一致的接口,应该使用和默认样式不一致的类选择器。
和js-前缀的类选择器类似,我推荐使用is-前缀的类选择器来定义那些要改变可视化组件的状态,这样的CSS规则可以像这样:
.pop-up.is-visible{}
注意到状态类选择器(is-visible)是连接在组件类选择器(pop-up)后,这很重要。因为状态规则是描述一个的状态,不应该单独列出。如此不同就可以用来区分更多和默认组件样式不同的状态样式。
另外,可以让我们可以编写测试场景来保证像is-*这样的前缀约定是否遵从。一种测试这些规则的方式是使用CSSLint和HTML Inspector。
更多关于特定状态类选择可以查阅Jonathan Snnok编写的非常优秀的SMACSS书籍。
JavaScript”选择器”
jQuery和新的API,像document.querySelectorAll,让用户非常简单地通过一种他们已经非常熟悉的语言–CSS选择器来查找DOM中的元素。虽然如此强大,但同样有CSS选择器已经存在的相同的问题。JavaScript选择器不应过度依赖于DOM结构。这样的选择器非常慢,并且需要更深入认识HTML知识。
就第一个例子来讲,负责HTML模板的开发者应该能在标记上做基本的改动,而不需担心破坏基本的功能。如果有个功能会被破坏,那么它就应该在标记上显而易见。
我已经提及到应该用js-前缀的类选择器来表示JavaScript钩子。另外针对消除样式和功能类选择器之间的二义性,需要在标记中表达出来。当某人编写HTML看到js-前缀的类选择器时,他就会明白这是别有用途的。但如果JavaScript代码使用特定的标记结构查找元素时,正在触发的功能在标记上就不那么明显了。
为了避免使用冗长而又复杂的选择器遍历DOM,坚持使用单一的类或者ID选择器。 考虑以下代码:
varsaveBtn=document.querySelector("#modal div:last-child > button:last-child")
这么长的选择器是可以节省你在HTML中添加一个类选择器,但同样让你的代码对于标记更改非常容易受到影响。如果设计者突然决定要把保持按钮放在左边,而让取消按钮放在右边,这样的选择器就不再匹配了。
一个更好的方式(使用上述的前缀方法)是仅仅使用类选择器。
varsaveBtn=document.querySelector(".js-save-btn")
现在标记可以更改它想改的,并且只要类选择还是在正确的元素上,一切都会很正常。
类选择器就是你的契约
使用合适的类选择器以及可预测的类名约定可以减少几乎每一种HTML,CSS和JavaScript之间的耦合。起初由于为了展现HTML需要知道很多类选择器的名称,这种在标记中使用很多类选择器看起来像是强耦合的迹象。但是我发觉,使用类选择器和传统编程设计中的事件或者观察者模式非常相似。在事件驱动编程中,为了不直接在对象A上调用对象B,而是对象A简单地在提供的环境中发布一个特定的事件,然后对象B能够订阅那个事件。这样,对象B就不需要知道任何关于对象A的接口,而仅仅需要知道监听什么事件。按理说,事件系统需要某种形式上的耦合,因为对象B需要知道订阅的事件名称,但和对象A需要知道对象B的公共方法相比,这已经更松散的耦合了。
HTML类选择器都非常相似。与CSS文件中定义复杂的选择器(就像HTML的内部接口一样)不同的是,它可以通过单一类选择器简单定义一个可视化组件的外观。CSS文件不需要关心HTML对类选择器的使用与否。同样,JavaScript不用那些需要更深入理解HTML结构的复杂DOM遍历功能,而是仅仅监听与类名一致的元素的用户交互。类选择器应该像是胶水一样,把HTML,CSS和JavaScript连接在一起。从个人经验得知,它们也是最容易以及最好的方式把三者技术连接起来,而不是混合过度。
未来
网页超文本技术工作小组(WHATWG)正在致力于web组件的规范,能让开发者把HTMLjs选择器,CSS和JavaScript绑定一起作为一个单独的组件或者模块,并与其它的页面元素进行交互封装。如果这个规范已经在大多数的浏览器中实现的话,那么我在本文中提供的很多建议就变得不那么重要了(因为代码和谁交互变得很清晰);但是无论如何,理解这些更广泛的原则以及为何需要它们仍然很重要。即使这些实践在Web组件时代会变得不那么重要,但其中的理论仍然适用。在大型团队和大型应用中的实践仍然要适用于小模块的编写中,反之则不需要。
结论
可维护的HTML,CSS和JavaScript的标志是每个开发者可以容易并且很自信地编写代码库的每个部分,而不需担心这些修改会无意中影响到其它不相关部分。阻止这样意想不到的后果的最佳方式之一是,通过一组能够表达其义的,任何开发者碰到时能想出它的用途的,可预测的人性化的类选择器名,把这三者技术结合在一起。
为避免上述的反模式,请把下述的原则谨记于心:
在HTML中这样运用类选择器经常会需要很多需要表现的类选择器,但获取的是可预见性和可维护性,这点值得肯定。毕竟,为HTML增加类选择器是相当容易的,不需要开发者有多少技能。摘自Nicolas Gallagher的原话:
当你要寻找一种方式来减少花费在编写和修改CSS的时间上来制作HTML和CSS时,这就涉及到你必须接受如果你想更改样式,你是不想花费更多时间去更改HTML元素上的类选择器。这对前端和后端开发者都有一定的实用性,任何人都可以重新安排预构建的乐高积木。这样没有人会去展示CSS的魔力了。
【今日微信公号推荐↓】
发表评论
热门文章
Spimes主题专为博客、自媒体、资讯类的网站设计....
一款个人简历主题,可以简单搭建一下,具体也比较简单....
仿制主题,Typecho博客主题,昼夜双版设计,可....
用于作品展示、资源下载,行业垂直性网站、个人博客,....
尘集杂货铺和官网1t5-cn
11月11日
[已回复]
希望主题和播放器能支持SQLite数据库,AI能多个讯飞星火