[置顶] HTML语义和前端架构
关于语义学
语义学是研究符号和意义之间的关系以及它们表示的内容。在语言学中,则主要是研究符号(例如单词,短语或者语音)在语言中所表达的意义。而在前端开发时,语义学则更多的关注HTML元素,属性以及它的值所表达的含义。而这些规范的语义可以帮助开发人员更好的理解网站上的信息。但是即使是以非常正式的形式来规范这些语义,程序员仍然会去修改这些语义。
各种HTML语义之间的区别
书写语义化的HTML是现代专业的前端开发基本原则之一。绝大部分的语义是和已经存在的内容或期盼的内容的本性息息相关的(例如:h1元素,lang属性,type属性的值为email)。
但是,不是所有的语义化都需要基于内容驱动的。类名是不可能没有语义的。不管使用什么名字,它们总是有特定的意思和目的的。类名的语义化可以不同于HTML元素。我们可以利用大家公认的语义化的元素,特定的HTML属性,微数据等从而来不要把这些本地网站或某些具体应用的语义化的目的搞混,通常是包含在属性中的值,例如class属性。
尽管HTML5规范中关于class部分不停的重复所谓的最佳实践:
并没有额外的规定开发人员如何使用类属性,但是鼓励开发人员使用描述内容的本质和属性的类而不是如何展示内容的类。
并没有天生的原因去这样做。事实上,当你工作于大项目或应用时,这种方法往往会成为一种阻碍。
- 内容层的语义化已经由HTML元素和其它属性提供了。
- 类名仅仅提供一点甚至没用的语义化信息给机器或者访问用户,除非是微格式.
- 类名的主要作用是为CSS和JavaScript提供钩子。如果你不需要为你的页面增加展示或者行为,那么你通常不需要在你的HTML里增加类。
- 类名应该能够传递有用的信息给开发者。当你阅读一个DOM片断时,类名应该能有助于你理解它在干嘛,尤其是在多人开发团队中前端开发并不是唯一接触HTML代码的人。
以下面非常简单的代码为例:
<divclass="news"><h2>News</h2>
[news content]
</div>
除了很明显的可以从内容看出的,类名本身并没有告诉你任何有用的信息。它没有告诉你任何并于组件架构和结构,并且它不能用于不是新闻的内容。把类名语义化和内容的本质紧紧的绑定在一起将会限制架构的扩展性以及复用性。例如其它开发人员无法将这些类名应用到其它地方。(译者注:这有点像类名和内容紧密耦合,一方改动将会影响到另一方,比如内容不是新闻了,则news这个类名也就不太合适了。)
内容无关的类名
一种替代的方法是从设计的结构和功能中获得类名。最便于复用的组件是那些类名独立于内容的组件。
我们宁愿使层与层之间的联系变得简洁明了,也不要类名和内容紧密的耦合在一起。这样做不会导致类名失去语义化,而只是意味着类名的语义化不是来源于内容而已。我们也不要害怕添加额外的HTML元素,如果它们能够帮助创造稳定的、灵活的、可重用的组件。这样做不会使HTML失去语义化,而只是意味着你使用的HTML元素超过了需要标记内容的最低标准。
前端架构
一个组件/模板/面向对象的架构的目标是开发一组有限的模块可以用于一系列不同类型的内容。大型应用中类名语义化重要的事情是它们由实用主义和它们的主要目的所驱动 - 提供有意义的、可扩展的、可复用的展示/行为钩子给开发人员使用。
可重用和便于组合的组件
可扩展的HTML/CSS必须依赖于HTML里的类来创建可重用的组件。一个灵活的和可重用的组件应该是既不依赖于特定的DOM结构,也不依赖于特定的HTML元素类型。它应该方便的加入到各种类型的容器中并且易于对其增加样式。如果需要,可以增加额外的HTML元素(相对于那些用于标记内容的HTML元素)来使组件更加稳定。一个非常好的例子是Nicole Sullivan 的media object.
组件可以方便的用于组合得益于尽量使用类而避免使用类型选择器。接下来的例子展示了btn组件和ullist组件的无法进行简单的组合。这里的问题在于.btn的权重要小于.uilist a(它会所有共亨的属性),并且ullist组件要求链接作为子结点(译者注:这违反了优秀组件不依赖于DOM结构的原则)。
.btn { /* styles */ }
.uilist { /* styles */ }
.uilist a { /* styles */ }
<nav class="uilist">
<a href="#">Home</a>
<a href="#">About</a>
<a class="btn" href="#">Login</a>
</nav>
一种可以使uilist组件很方便的和其它组件组合的改进方案是通过类来给子元素加样式。尽管这有助于降低CSS规则的权重,但是最主要的好处在于它可以将样式应用到任何类型的子元素上。
.btn { /* styles */ }
.uilist { /* styles */ }
.uilist-item { /* styles */ }
<nav class="uilist">
<a class="uilist-item" href="#">Home</a>
<a class="uilist-item" href="#">About</a>
<span class="uilist-item">
<a class="btn" href="#">Login</a>
</span>
</nav>
JavaScript专用类
使用一定形式的JavaScript专用类可以减少由于样式或结构的改动从而影响应用它上面的JavaScript行为。我找到一种有帮助的方法是为JavaScript钩子使用特定的类 -js-* - 并且不在它们上面应用任何样式。
<a href="/login" class="btn btn-primary js-login"></a>
这样你就可以减少因为样式或结构的改变从而无意中影响了必须的JavaScript行为和复杂的功能。
组件修饰符(modifiers)
组件经常会有部分样式和基础组件不同的地方,例如背景或者边框。有两种主要的模式可以用来创建这些变化的部分。我称之为"单类模式"和"多类模式"。
单类模式
.btn, .btn-primary { /* button template styles */ }
.btn-primary { /* styles specific to save button */ }
<button class="btn">Default</button>
<button class="btn-primary">Login</button>
多类模式
.btn { /* button template styles */ }
.btn-primary { /* styles specific to primary button */ }
<button class="btn">Default</button>
<button class="btn btn-primary">Login</button>
如果你使用CSS预处理器,你将会使用Saas的@extend功能来减少使用单例模式的维护工作。但是尽管预处理器有这些好处,我还是喜欢使用多类模式和在HTML里增加修改的类。
我已经发现这是一种可以处理大规模应用的模式。例如,我们以btn模块为基础增加5个类型的Button,以及3个不同大小的Button。使用多类模式你最后需要9个类来满足我们的需求,而使用单类模式最后则需要24个类。
It is also easier to make contextual tweaks to a component, if absolutely necessary. 你也许想去对出现在其它组件中的任何btn组件作些细微的调整。
/* "multi-class" adjustment */
.thing .btn { /* adjustments */ } /* "single-class" adjustment */
.thing .btn,
.thing .btn-primary,
.thing .btn-danger,
.thing .btn-etc { /* adjustments */ }
多类模式意味着你只需要一个组件内的选择器就可以定位任何组件内的btn系列的元素。而单类模式则意味着你需要为每个类型的button都增加一个选择器,并且调整选择器当一个新的button类型被创建时。
结构化类名
当创建组件以及基于它们的主题(themes)时,一些类用于组件的边界,还有一些类用于组件修饰符(modifiers),另外一些则用于关联一组DOM节点和一个非常好大的抽象的展现层组件。
去推断btn(组件),btn-primary(修饰符),btn-group(组件)和btn-group-item(组件,子对象)它们之间的关系是很困难的,因为它们的名称在表面上无法看出它们的目的。它们没有一致的命名模式。
在过去一年,我一直在实验命名规则,它可以帮我更快地理解DOM片断里节点之间的展示关系,而不是通过在HTML, CSS, JS文件间来回切换把网站的架构拼凑在一起。这个模式是受到BEM system命名方法的影响和启发,但是采用了更便于浏览查看的形式。
t-template-name
t-template-name--modifier-name
t-template-name__sub-object
t-template-name__sub-object--modifier-name component-name
component-name--modifier-name
component-name__sub-object
component-name__sub-object--modifier-name is-state-type js-action-name
js-component-type
我把其中一些结构当作抽象的“模板”,其它作为更独特的组件(它们通常是基于模板),但是这些独特性不是总是需要的。这仅仅是我目前发现的有用的命名规则。它可以采用任何形式。但它的好处在于移除了那些模棱两可的类名,例如那些仅仅依靠连接符(-),下划线(_)或者驼峰命名方式。
如需转载,请注明来自: BorisHuai前端修炼 > HTML语义和前端架构
来自:About HTML semantics and front-end architecture
[置顶] HTML语义和前端架构的更多相关文章
- [置顶] 漫谈SOA(面向服务架构)
面向服务架构的思想在整个软件的架构中已经不是什么新鲜的东西.我简单的认为服务化是模块化的延伸,所以服务化有着和模块化类似的优点和缺点.这里不再讨论这些服务定义服务与服务之间的通信协议(像WSDL等等) ...
- [置顶] Web用户的身份验证及WebApi权限验证流程的设计和实现 (不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!!)
转发 http://blog.csdn.net/besley/article/details/8516894 不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!! [ ...
- 基于AngularJS的企业软件前端架构[转载]
这篇是我参加QCon北京2014的演讲内容: 提纲: 企业应用在软件行业中占有很大的比重,而这类软件多数现在也都采用B/S的模式开发,在这个日新月异的时代,它们的前端开发技术找到了什么改进点呢? B/ ...
- 用“MEAN”技术栈开发web应用(一)AngularJs前端架构
前言 不知何时突然冒出“MEAN技术栈”这个新词,听起来很牛逼的样子,其实就是我们已经熟悉了的近两年在前端比较流行的技术,mongodb.express.angularjs.nodejs,由于这几项技 ...
- 前端leader找我谈心:我是如何从刚毕业的前端菜鸟一步步成长为前端架构师的?
谈谈学习 我做前端已经有五年的时间了,从大学刚毕业的时候,我是一个完全什么都不懂的小白.虽然我大学里学的是软件工程专业,但是因为在大学里荒废学业,每天只知道打游戏,基本上到大学毕业之前我是什么都不会的 ...
- jQuery实现表格行上移下移和置顶
jQuery实现表格行上移下移和置顶 我们在操作列表数据的时候,需要将数据行排列顺序进行调整,如上移和下移行,将行数据置顶等,这些操作都可以在前端通过点击按钮来完成,并且伴随着简单的动态效果,轻松实现 ...
- MySQL 上移/下移/置顶
在编写网站系统时,难免会用到上移.下移.置顶的功能,今天小编就介绍一下我的思路. 首先,需要一张数据表: CREATE TABLE `a` ( `id` ) NOT NULL AUTO_INCREME ...
- 前端架构师亲述:前端工程师成长之路的 N 问 及 回答
问题回答者:黄轶,目前就职于 Zoom 公司担任前端架构师,曾就职于滴滴和百度. 1. 前端开发 问题 大佬,能分享下学习路径么,感觉天天忙着开发业务,但是能力好像没有太大提升,不知道该怎么充实自己 ...
- 在UWP中页面滑动导航栏置顶
最近在研究掌上英雄联盟,主要是用来给自己看新闻,顺便copy个界面改一下段位装装逼,可是在我copy的时候发现这个东西 当你滑动到一定距离的时候导航栏会置顶不动,这个特性在微博和淘宝都有,我看了@ms ...
随机推荐
- C++不同进制整数
在C++的整数常量中,整数分为十进制整数.八进制整数和十六进制整数. 那给出一个整型常量怎样区分是何种进制呢?/给出一个整型常量,如100,默认是十进制数,如果在该数前加0,如0100,则此数表示为八 ...
- 深入php面向对象和模式
前两章是php历史和概论,略过. 第三章 对象基础 3.1 类和对象 类,是用于生成对象的代码模版. public 公有的,都可调用. protected 保护的, 只有本类和子类可以调用. priv ...
- WM_ACTIVATE
参数: fActive = LOWORD(wParam); // activation flag fMinimized = (BOOL)HIWORD(wParam); // minimized ...
- 【Oracle连接字符串】【Oracle Net Manager 服务命名配置】【PL/SQL 登陆数据库】
连接数据库的几个重要参数: 1. 登陆用户名:user: 2. 登录密码:password: 3. 存放数据库的服务器地址(server_ip)和端口(server_port): 4. 数据库名(db ...
- linux文件系统-基本磁盘2
直入主题-基本磁盘 硬盘数据按照不同特点和作用大致分为5部分:MBR区.DBR区.FAT区.DIR区和DATA区 1.MBR MBR(Main Boot Record 主引导记录区)位于整个硬盘的0磁 ...
- php Late Static Bindings延迟静态绑定
官网说道: As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to ref ...
- C#.Net 如何动态加载与卸载程序集(.dll或者.exe)3---- 动态加载Assembly应用程序
下载 supergraphfiles.exe 示例文件. 应用程序体系结构 在我专攻代码之前,我想谈谈我尝试做的事.您可能记得,SuperGraph 让您从函数列表中进行选择.我希望能够在具体的目录中 ...
- WINCE6.0去掉桌面快捷方式
WINCE6.0去掉桌面快捷方式,主要是修改xxx.bat文件,比如我要去掉My Documents和Media Player的快捷方式. (1) 去掉My Documents桌面快捷方式 找到 ...
- 使用ANT打包Android应用
大家好,今天来分享一下如何使用ANT打包Android应用. 通常我们习惯用eclipse来开发Android程序,它会自动帮我们打包当前的应用程序.如果在Navigator视图下,我们可以看到以下几 ...
- 1837. Isenbaev's Number(floyd)
1837 被数据结构部分打击的不行了 换地 刷点简单的 图论第一题 floyd水过 #include <iostream> #include<cstdio> #include& ...