Web 前端开发风格指南
风格指南用于统一开发方式与代码书写风格。
推荐使用 EditorConfig 来配置编辑器,方便编写统一书写风格的代码。同时使用 Lint 来做代码质量检测。
基本规范
基本规范可引用各语言的社区推荐风格,如:
- Google:
- Google HTML/CSS Style Guide
- Google JavaScript Style Guide
- GitHub:
- Markup & Templates Styleguide
- CSS Styleguide
- JavaScript Styleguide
- Other:
- HTML
- CSS
- Sass
- JavaScript
注释
应用场景:
- 模块描述
- 函数方法
- 大段代码
- 复杂算法
- Hack
文档化:
按照文档规范来书写易于阅读,且能被机器解读的注释,配合使用对应的预处理器,可以自动生成文档。
- KSS
- JSDoc
- TomDoc
风格:
comment.html
<header>
</header> <!-- / header -->
<div id="wrapper">
</div> <!-- / #wrapper -->
<div class="module">
</div> <!-- / .module -->
comment.css
/* ==========================================================================
区块注释段
========================================================================== */
/* 子区块注释段
-------------------------------------------------------------------------- */
/**
* 分组注释段
* 用于多行的释义或文档。
* 1. 注释1。
* 2. 注释2。
*/
.selector {
property1: value1; /* 1 */
property2: value2; /* 2 */
}
/* 基本注释 */
comment.scss
// ==========================================================================
// 区块注释段
// ==========================================================================
// 子区块注释段
// --------------------------------------------------------------------------
//
// 分组注释段
// 用于多行的释义或文档。
//
// 基本注释
component.scss
// A button suitable for giving a star to someone.
// Experimental: An alternative signup button styling used in AB Test #195.
// Deprecated: Styling for legacy wikis. We'll drop support for these wikis on
// July 13, 2007.
//
// :hover - Subtle hover highlight.
// .star-given - A highlight indicating you've already given a star.
// .star-given:hover - Subtle hover highlight on top of star-given styling.
// .disabled - Dims the button to indicate it cannot be used.
//
// Compatible in IE6+, Firefox 2+, Safari 4+.
// Compatibility untested.
//
// Styleguide 2.1.3.
// No styleguide reference.
mixin.scss
// Creates a linear gradient background, from top to bottom.
//
// $start - The color hex at the top.
// $end - The color hex at the bottom.
comment.js
/* ==========================================================================
区块注释段
========================================================================== */
/* 子区块注释段
-------------------------------------------------------------------------- */
/**
* 模块简介
*
* 具体细节
*
* @param {string} args1 参数 1。
* @param {array} args2 参数 2。
* @returns void
*/
UI 组件设计模式
相对于以页面为单位的开发方式,建议以构建组件系统的方式来开发。
- Atomic Design
- BEM
- OOCSS
- SMACSS
为了合理划分组件并分离内容、样式、行为,建议采用如下设计模式。
原子 - 分子 - 组织 - 模版 - 页面
HTML(语义)
class 区分 UI 与业务,使用attribute加强语义与配置行为。
<div class="model component" attribute="value" data-attribute="value">
<div class="component-descendant">
...
</div>
</div><!-- / .component -->
<div class="component--modifier" data-attribute="value">
<div class="component-descendant is-state">
...
</div>
</div><!-- / .component--modifier -->
CSS(组件)
规则书写
- Layout: The position of the element in space. Eg.: position, top, z-index.
- Box: The element itself. Eg.: display, overflow, box-sizing.
- Visual: Design of the element. Eg.: color, border, background.
- Type: Typesetting of the element. Eg.: font-family, text-transform.
模块分组
Abstracts ----------- 抽象
├── Variables ----- 变量
| └── Palette --- 调色盘
├── Functions ----- 函数
├── Mixins -------- 混合宏
└── Placeholders -- 占位符
Vendors ------------- 第三方框架、库、插件
Normalize ----------- 标准化
Typography ---------- 文本版式
Icons --------------- 图标
Layout -------------- 布局规则
Components ---------- UI 组件
Themes -------------- 主题风格
Helpers ------------- 辅助工具
[Pages] ------------- 页面专属样式
[Print] ------------- 打印样式
[Shame] ------------- 补丁
变量命名
<property>-<value>[--componentName]
模块
命名
<component>[-descendant|--modifier]
.component ------------------------------- 组件
.component-descendant -------------------- 组件子模块
.component--modifier --------------------- 组件派生类
.is-state -------------------------------- 组件状态
.u-util ---------------------------------- 工具
.js-hook --------------------------------- JavaScript 专属钩子
.shame-classname ------------------------- 补丁
代码组织
%model {
// minimum equipment
.model-descendant {}
}
.model {
@extend %model;
.model-descendant {}
}
.model--modifier {
@extend %model;
.model-descendant {}
}
.page--model {}
.page--model-descendant {}
注解:
- 尽量降低选择器的优先级。
- 如果 HTML 结构明确,可直接使用元素选择器。
- 组件中的行为可以依赖于组件结构。而不同组件拥有相同行为时,可以将 JavaScript 绑定到 .js-hook 上。
- shame 补丁样式集中存放,详细注释并定期修复。
- 由于 IE 6 不支持部分常用选择器(如:子选择器.foo > .bar,链式选择器 .foo.bar 等),导致无法使用 .component-descendant.is-state,因此采用.is-component-descendant-state命名约定来弥补不足。
JavaScript(事件流)
随着用户体验的不断改善,JavaScript 代码的规模也会不断增加,因此建议一开始就进行基本的模块管理,或者使用框架、库来组织代码。
Web Site
模块分组
Vendor ----------------------------------- 第三方框架、库、插件
Util ------------------------------------- 通用工具
Base ------------------------------------- 应用初始化
Common ----------------------------------- 全局属性与方法
Component -------------------------------- 通用 UI 组件
Business Logic --------------------------- 应用业务逻辑
Main ------------------------------------- 全局执行代码
Entry ------------------------------------ 各页面入口
注解:
- Component 完全脱离 Business Logic,并且推荐开源 Component。
模块实现
/**
* @desc Module Organization
* @see http://pinkyjie.com/2013/12/18/rock-your-web-page-in-bakcbone-way/
*/
// Base
(function(root, $) {
root.App = {
view: {}
};
root.$document = $(document);
root.$window = $(window);
root.EventBus = {
trigger: function(event, data) {
var e = $.Event(event);
e.param = data;
$document.trigger(e);
},
on: function(event, callback) {
$document.on(event, callback);
},
off: function(event) {
$document.off(event);
}
};
}(this, jQuery));
// Common
// Util
(function(exports, $) {
// TODO
exports.extend = function() {};
}(App, jQuery));
// Component
(function(exports, $) {
var component = function(element) {
this.$el = $(element);
this.model = null;
// TODO
_.bindAll(this, 'submit', 'create', 'destroy');
// 模块内部的交互使用事件委托
this.$el
.on('submit', 'form', this.submit);
// 模块与模块之间的交互使用观察者模式
EventBus
.on('Component:create', this.create)
.on('Component:destroy', this.destroy);
};
// TODO
_.extend(component.prototype, {
render: function() {
this.reset();
console.log('render');
},
reset: function() {
console.log('reset');
},
submit: function() {
console.log('submit');
},
create: function(event) {
console.log('create');
},
destroy: function(event) {
console.log('destroy');
}
});
exports.view.component = component;
}(App, jQuery));
// Main
(function(exports, $) {
exports.InitPage = function() {
var componentView = new exports.view.component('.component');
componentView.render();
};
}(App, jQuery));
// Execution
// 在 HTML 模板中调用。
// 之前的模块大部分都是声明,耗时较少。代码只在对应的模板中运行。
App.InitPage();
模块管理
使用 AMD、CommonJS 及 ES Harmony 编写模块化的 JavaScript。
Web App
@TODO
模块通用化
在满足应用本身的需求之后,建议将模块从应用中解耦出来,方便集成到其他应用。
jQuery 插件
/**
* @desc jQuery 插件设计模式 - Data API
* @see Bootstrap
*/
(function($) {
// Module Public Class Definition
// ==============================
var Module = function(element, options) {
this.$element = $(element);
this.options = options;
};
Module.prototype.method = function() {
// do something...
};
// Module Default Options
Module.DEFAULTS = {
'key': 'value'
};
// Module jQuery Plugin Definition
// ===============================
var old = $.fn.module;
$.fn.module = function(option) {
return this.each(function() {
var $this = $(this),
data = $this.data('module'),
options = $.extend(
{},
Module.DEFAULTS,
$this.data(),
typeof option == 'object' && option
);
if (!data) $this.data('module', (data = new Module(this, options)));
if (typeof option == 'string') data[option]();
});
};
$.fn.module.Constructor = Module;
// Module No Conflict
// ==================
$.fn.module.noConflict = function() {
$.fn.module = old;
return this;
};
// Module Data-API
// ===============
$(document).on('event.module.data-api', '[data-toggle="module"]', function(e) {
e.preventDefault();
$(this).module('method');
// do something...
});
})(jQuery);
其他
省略行末分号
如果下一行的第一个token是 ( , [ , / , + , - 这五个字符之一的话,JavaScript 将不会自动在上一行句尾加上分号。所以注意这类情况。