前端编码规范

基本原则

  • 结构、样式、行为分离
  • 统一缩进(建议 两个空格)
  • 文件编码统一 不带BOMUTF-8
  • 一律使用小写字母
  • 省略外链资源 URL 协议部分(FTP等其他URL不省略)
  • 统一注释

HTML

  • 标签
    • 自闭合无需闭合img input br hr
    • 可选闭合需闭合
    • 尽量减少标签
  • class & id
    • 以功能或内容命名, 不以表现形式命名
    • -分隔
  • 属性顺序 id > class > name > data-xxx > src,for,type,href > title,alt > aria-xxx,role
  • 属性统一使用双引号
  • 语义嵌套及严格嵌套约束 参考:WEB标准系列-HTML元素嵌套
    • <li>用于<ul><ol>
    • <dd> <dt> 用于 <dl>
    • <thead> <tbody> <tfoot> <tr> <td> 用于 <table>
    • inline-Level 元素,仅可以包含文本或其它 inline-Level 元素;
    • <a>里不可以嵌套交互式元素<a><button><select>等;
    • <p>里不可以嵌套块级元素<div><h1>~<h6><p><ul>/<ol>/<li><dl>/<dt>/<dd><form>等。
  • HEAD
    • 文档类型 <!DOCTYPE html>
    • 语言属性 <lang="zh-cmn-Hans">
    • 字符编码(必须是<head>标签的第一个子元素) <meta charset="utf-8">
    • 优先使用最新内核 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    • SEO优化 <meta name="keywords" content="your keywords"> <meta name="description" content="your description"> <meta name="author" content="author,email address">
    • viewport <meta name="viewport" content="width=device-width, initial-scale=1.0">
    • iOS图标
      • apple-touch-icon 图片自动处理成圆角和高光等效果;
      • apple-touch-icon-precomposed 禁止系统自动添加效果,直接显示设计原图;
    • favicon <link rel="shortcut icon" href="path/to/favicon.ico">

HEAD模板

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Style Guide</title>
  <meta name="description" content="不超过150个字符">
  <meta name="keywords" content="">
  <meta name="author" content="name, email@gmail.com">

  <!-- 为移动设备添加 viewport -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- iOS 图标 -->
  <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png">

  <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
  <link rel="shortcut icon" href="path/to/favicon.ico">
</head>

HTML标签语义化

标签语义
<p>段落
<h1> <h2> <h3> ...标题
<ul>无序列表
<ol>有序列表
<blockquote>大段引用
<cite>一般引用

<b> 为样式加粗而加粗
<storng> | 为强调内容而加粗
<i> | 为样式倾斜而倾斜
<em> | 为强调内容而倾斜
<code> | 代码标识
<abbr> | 缩写

CSS

  • 以组件为单位组织代码
  • 组件块和子组件块以及声明块之间使用一空行分隔,子组件块之间三空行分隔;
  • 如果使用了多个 CSS 文件,将其按照组件而非页面的形式分拆,因为页面会被重组,而组件只会被移动;
  • 避免选择器嵌套层级过多, 尽量少于3级
  • 避免Class ID叠加使用
  • 声明块
    • 选择器分组时, 保持独立的选择器占用一行
    • 声明块的左括号 { 前添加一个空格;
    • 声明块的右括号 } 应单独成行;
    • 声明语句中的 : 后应添加一个空格;
    • 声明语句应以分号 ; 结尾;
    • 一般以逗号分隔的属性值,每个逗号后应添加一个空格;
    • rgb()、rgba()、hsl()、hsla() 或 rect() 括号内的值,逗号分隔,但逗号后不添加一个空格;
    • 对于属性值或颜色参数,省略小于 1 的小数前面的 0 (例如,.5 代替 0.5;-.5px 代替 -0.5px);
    • 十六进制值应该全部小写和尽量简写,例如,#fff 代替 #ffffff;
    • 避免为 0 值指定单位
  • 声明顺序 Positioning > Box model > Typographic > Visual
  • url() 、属性选择符、属性值使用双引号。
  • 将媒体查询(Media query)放在尽可能相关规则的附近
  • 不要使用 @import
  • 链接样式顺序 a:link -> a:visited -> a:hover -> a:active(LoVeHAte)
  • 使用Autoprefixer自动添加浏览器前缀, 书写CSS无需添加浏览器前缀
/* ==========================================================================
   组件块
 ============================================================================ */

/* 子组件块
 ============================================================================ */

由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。盒模型决定了组件的尺寸和位置,因此排在第二位。其他属性只是影响组件的内部(inside)或者是不影响前两组属性。

.declaration-order {
  /* Positioning */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;

  /* Box model */
  display: block;
  box-sizing: border-box;
  width: 100px;
  height: 100px;
  padding: 10px;
  border: 1px solid #e5e5e5;
  border-radius: 3px;
  margin: 10px;
  float: right;
  overflow: hidden;

  /* Typographic */
  font: normal 13px "Helvetica Neue", sans-serif;
  line-height: 1.5;
  text-align: center;

  /* Visual */
  background-color: #f5f5f5;
  color: #fff;
  opacity: .8;

  /* Other */
  cursor: pointer;
}

CSS 网页字体排版

字体

内文字体

p { font-family: "Georgia", "Times New Roman", "Songti SC", "SimSun", serif; }

标题字体

h1, h2, h3, h4, h5, h6 { font-family: "Lucida Grande", "Helvetica Neue", "Arial", "Hiragino Sans GB", "Noto Sans CJK SC", "Heiti SC", "Microsoft YaHei", "WenQuanYi Microhei", sans-serif; }
字号

将内文以 16px 作为字号
标题 h1, h2, h3, h4, h5, h616px 作为字号基础,按同比例的递减

p  { font-size: 16px; }
h1 { font-size: 2em; }
h2 { font-size: 1.8em; }
h3 { font-size: 1.6em; }
h4 { font-size: 1.4em; }
h5, h6 { font-size: 1.2em; }
行高

将内文以 1.7em 作为行高
标题 h1, h2, h3, h4, h5, h6 以 1.5em 作为行高.

p { line-height: 1.7em; }
h1, h2, h3, h4, h5, h6 { line-height: 1.5em; }
段落间距
p { margin-bottom: 1.7em; }
h1, h2, h3, h4, h5, h6 {
  margin-top: .7em;
  margin-bottom: 0.2em;
}
齐头尾
p {
text-align: justify;
text-justify: inter-ideographic;
}
断词使中英文混排时字符间距不会被齐头尾拉的不均匀
p { word-break: break-all; }

Less

  • 代码顺序 @import > 变量声明 > 样式声明
  • @import .less不得省略, 用双引号
  • Mixin
    • 在定义 mixin 时,如果 mixin 名称不是一个需要使用的 className,必须加上括号,否则即使不被调用也会输出到 CSS 中。
    • 如果混入的是本身不输出内容的 mixin,需要在 mixin 后添加括号(即使不传参数),以区分这是否是一个 className。
  • 避免嵌套层级过多, 限制在2层
  • 可以使用字符串插值使变量嵌入字符串中 @base-url: "http://assets.fnord.com"; background-image: url("@{base-url}/images/bg.png");

命名(从组件方式思考命名)

  • Components 至少以两个单词命名,通过-分离 .like-button .search-form .article-card
  • Elements (Element 是 Components 中的元素)
    • 类名尽可能仅有一个单词
    • 多个单词应直接连接
    • 避免标签选择器(性能稍弱,表意不明)
  • Variants(变体) 带有前缀-
    • .-wide .-short .-disabled .title.-small
    • 避免定位属性
      • Positioning (position, top, left, right, bottom)
      • Floats (float, clear)
      • Margins (margin)
      • Dimensions (width, height)
  • 头像 logos等元素应设置 固定尺寸
  • 在父元素中设置定位
  • 避免过分嵌套
className命名

常见class关键词:

  • 布局类:header, footer, container, main, content, aside, page, section
  • 包裹类:wrap, inner
  • 区块类:region, block, box
  • 结构类:hd, bd, ft, top, bottom, left, right, middle, col, row, grid, span
  • 列表类:list, item, field
  • 主次类:primary, secondary, sub, minor
  • 大小类:s, m, l, xl, large, small
  • 状态类:active, current, checked, hover, fail, success, warn, error, on, off
  • 导航类:nav, prev, next, breadcrumb, forward, back, indicator, paging, first, last
  • 交互类:tips, alert, modal, pop, panel, tabs, accordion, slide, scroll, overlay,
  • 星级类:rate, star
  • 分割类:group, seperate, divider
  • 等分类:full, half, third, quarter
  • 表格类:table, tr, td, cell, row
  • 图片类:img, thumbnail, original, album, gallery
  • 语言类:cn, en
  • 论坛类:forum, bbs, topic, post
  • 方向类:up, down, left, right
  • 其他语义类:btn, close, ok, cancel, switch; link, title, info, intro, more, icon; form, label, search, contact, phone, date, email, user; view, loading…

简单规则

  • 以中划线连接,如.item-img
  • 使用 两个中划线表示特殊化,如.item-img.item-img–small表示在.item-img的基础上特殊化
  • 状态类直接使用单词,参考上面的关键词,如.active, .checked
  • 图标以icon-为前缀(字体图标采用.icon-font.i-name方式命名)。
  • 模块采用关键词命名,如.slide, .modal, .tips, .tabs,特殊化采用上面两个中划线表示,如.imgslide–full, .modal–pay, .tips–up, .tabs–simple
  • js操作的类统一加上js-前缀
  • 不要超过四个class组合使用,如.a.b.c.d

JavaScript

  • 注释 如无必要勿增注释, 如有必要尽量详尽, 只使用//, 避免使用/*...*/
    • 函数方法注释包含函数说明参数和返回值及返回值类型, 如果函数是内部函数可以使用@inner标识
    • 文件注释 应该提供文件的大体内容, 它的作者, 依赖关系和兼容性信息。如下:
/**
 * 函数描述
 *
 * @param {string} p1 参数1的说明
 * @param {string} p2 参数2的说明,比较长
 *     那就换行了.
 * @param {number=} p3 参数3的说明(可选)
 * @return {Object} 返回值描述
 */
/**
 * @fileoverview Description of file, its uses and information
 * about its dependencies.
 * @author user@meizu.com (Firstname Lastname)
 * Copyright 2009 Meizu Inc. All Rights Reserved.
 */
  • 命名
    • 变量 驼峰命名法
    • 私有属性变量方法 _开头
    • 常量 全部字母大写, _分隔
    • 函数及函数的参数 驼峰命名法
    • 类 单词首字母大写, 类的方法及属性 驼峰命名法
    • 枚举变量 单词首字母大写, 枚举属性 全部字母大写, _分隔
    • 多个单词组成的缩写词, 在命名中, 根据当前命名法和出现的位置, 所有字母的大小写与首字母大小写保持一致
  • 命名词法
    • 类名 使用名词 function Engine(options) {}
    • 函数名,使用动宾短语。 function getStyle(element) {}
    • boolean类型的变量 使用 is 或 has 开头。var isReady = false; var hasMoreCommands = false;
    • Promise 对象用动宾短语的进行时表达。var loadingData = ajax.get('url'); loadingData.then(callback);
  • 接口命名规范 (1.可读性强 2.不与jQuery社区习惯冲突 3.尽量写全不用缩写,除非下表中已经约定的)
常用词说明
options表示选项,与 jQuery 社区保持一致,不要用 config, opts 等
active表示当前,不要用 current 等
index表示索引,不要用 idx 等
trigger触点元素
triggerType触发类型、方式
context表示传入的 this 对象
object推荐写全,不推荐简写为 o, obj 等
element推荐写全,不推荐简写为 el, elem 等
length不要写成 len, l
prevprevious 的缩写
nextnext 下一个
constructor不能写成 ctor
easing示动画平滑函数
minminimize 的缩写
maxmaximize 的缩写
DOM不要写成 dom, Dom
.hbs使用 hbs 后缀表示模版
btnbutton 的缩写
link超链接
title主要文本
img图片路径(img标签src属性)
datasethtml5 data-xxx 数据接口
theme主题
className类名
classNameSpaceclass 命名空间
  • True False
    • 类型检测 优先使用typeof
    • 对象检测 使用instanceof
    • null 或 undefined 检测使用 == null
    • 返回 false null undefined '' 0
    • 返回 true '0' [] {}
  • for-in循环只用于object/map/hash遍历, 因为Array上使用for-in循环会对所有出现在原型上的对象进行遍历
  • 二元及三元操作符始终写在前一行
  • 三元操作符替代if...else
  • && || 设置默认值和替代多个if嵌套判断
  • 正则表达式 仅准用.test().exec()。不准用"string".match()
  • 多个参数使用对象字面量存储

jQuery

  • 使用最新版本的jQuery
  • jQuery变量 以$开头, 并缓存到本地变量中复用, 使用驼峰命名法命名
  • jQuery选择器
    • 尽量使用ID选择器
    • 父元素选择子元素用.find()方法性能会更好
  • DOM 操作, 尽量先与节点分离, 操作结束后再插入节点
  • 字符串连接 array.join('') >+ > .append()
  • 事件
    • 如果需要,对事件使用自定义的 namespace,这样容易解绑特定的事件,而不会影响到此 DOM 元素的其他事件监听;
    • 对 Ajax 加载的 DOM 元素绑定事件时尽量使用事件委托。事件委托允许在父元素绑定事件,子代元素可以响应事件,也包括 Ajax 加载后添加的子代元素;
$("#myLink").on("click.mySpecialClick", myEventHandler);
$("#myLink").unbind("click.mySpecialClick");
// Not recommended
$("#list a").on("click", myClickHandler);
// Recommended
$("#list").on("click", "a", myClickHandler);
  • 链式写法 1.尽量使用链式写法而不是用变量缓存或者多次调用选择器方法; 2.当链式写法超过三次或者因为事件绑定变得复杂后,使用换行和缩进保持代码可读性;
  • CSS不要写在jQuery里面
  • 避免使用 jQuery 实现动画
    • 禁止使用slideUp/Down() fadeIn/fadeOut() 等方法;
    • 尽量不使用animate()方法;

jQuery 插件模板

// jQuery Plugin Boilerplate
// A boilerplate for jumpstarting jQuery plugins development
// version 1.1, May 14th, 2011
// by Stefan Gabos

// remember to change every instance of "pluginName" to the name of your plugin!
(function($) {

    // here we go!
    $.pluginName = function(element, options) {

        // plugin's default options
        // this is private property and is  accessible only from inside the plugin
        var defaults = {

            foo: 'bar',

            // if your plugin is event-driven, you may provide callback capabilities
            // for its events. execute these functions before or after events of your
            // plugin, so that users may customize those particular events without
            // changing the plugin's code
            onFoo: function() {}

        }

        // to avoid confusions, use "plugin" to reference the
        // current instance of the object
        var plugin = this;

        // this will hold the merged default, and user-provided options
        // plugin's properties will be available through this object like:
        // plugin.settings.propertyName from inside the plugin or
        // element.data('pluginName').settings.propertyName from outside the plugin,
        // where "element" is the element the plugin is attached to;
        plugin.settings = {}

        var $element = $(element), // reference to the jQuery version of DOM element
             element = element;    // reference to the actual DOM element

        // the "constructor" method that gets called when the object is created
        plugin.init = function() {

            // the plugin's final properties are the merged default and
            // user-provided options (if any)
            plugin.settings = $.extend({}, defaults, options);

            // code goes here

        }

        // public methods
        // these methods can be called like:
        // plugin.methodName(arg1, arg2, ... argn) from inside the plugin or
        // element.data('pluginName').publicMethod(arg1, arg2, ... argn) from outside
        // the plugin, where "element" is the element the plugin is attached to;

        // a public method. for demonstration purposes only - remove it!
        plugin.foo_public_method = function() {
            // code goes here
        }

        // private methods
        // these methods can be called only from inside the plugin like:
        // methodName(arg1, arg2, ... argn)

        // a private method. for demonstration purposes only - remove it!
        var foo_private_method = function() {
            // code goes here
        }

        // fire up the plugin!
        // call the "constructor" method
        plugin.init();
    }

    // add the plugin to the jQuery.fn object
    $.fn.pluginName = function(options) {

        // iterate through the DOM elements we are attaching the plugin to
        return this.each(function() {

            // if plugin has not already been attached to the element
            if (undefined == $(this).data('pluginName')) {

                // create a new instance of the plugin
                // pass the DOM element and the user-provided options as arguments
                var plugin = new $.pluginName(this, options);

                // in the jQuery version of the element
                // store a reference to the plugin object
                // you can later access the plugin and its methods and properties like
                // element.data('pluginName').publicMethod(arg1, arg2, ... argn) or
                // element.data('pluginName').settings.propertyName
                $(this).data('pluginName', plugin);
            }
        });
    }
})(jQuery);

ES6

  • 块级作用域
    • let取代var
    • let const优先使用const(所有的函数应设置为const常量,let表示的变量,只应出现在单线程运行的代码中,不能是多线程共享的,这样有利于保证线程安全。)
  • 字符串
    • 静态字符串使用单引号
    • 动态字符串使用反引号
  • 解构赋值
    • 数组成员赋值,优先使用解构赋值 const [first, second] = [1, 2];
    • 函数的参数如果是对象的成员,优先使用解构赋值。
    • 如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。
  • 对象
    • 单行定义的对象,最后一个成员不以逗号结尾
    • 多行定义的对象,最后一个成员以逗号结尾
    • 对象尽量静态化,不得随意添加属性.如果添加属性不可避免,使用Object.assign()
    • 如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义。
    • 对象属性和方法尽量采用简洁表达法
  • 数组
    • 使用扩展运算符...拷贝数组
    • 使用Array.from()将类数组对象转为数组
  • 函数
    • 立即执行函数可以写成箭头函数 (()=>{console.log('a');})()
    • 能用箭头函数尽量用箭头函数,不仅简洁而且绑定了this
    • 箭头函数取代Function.prototype.bind,不应再用self/_this/that绑定this
    • 所有配置项都应该集中在一个对象,放在最后一个参数,布尔值不可以直接作为参数。
    • 不要在函数体内使用arguments变量,使用rest运算符(...)代替。
    • 使用默认值语法设置函数参数的默认值。
  • Map结构
    • 只有模拟实体对象时,才使用Object。如果只是需要key:value的数据结构,使用Map。因为Map有内建的遍历机制。
  • class
    • class取代prototype操作
    • 使用extends实现继承,这样不会有破坏instanceof运算的危险。
  • module
    • import 取代 require
    • export 取代 module.exports
    • 如果模块只有一个输出值,就使用export default,如果模块有多个输出值,就不使用export default,不要export default与普通的export同时使用。
    • 不要在模块输入中使用通配符。因为这样可以确保你的模块之中,有一个默认输出(export default)。
    • 模块输出函数, 函数首字母小写
    • 模块输出对象,对象首字母大写

代码校验

代码验证

ESlint 使用

  • $ npm i -g eslint
  • $ npm i -g eslint-config-airbnb
  • .eslintrc文件,配置ESLint。{"extends": "eslint-config-airbnb"}

参考

    原文作者:KeKeMars
    原文地址: https://www.jianshu.com/p/8bb99715ea44
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞