Javascript Styleguide

Push 至 Git 库前,必须先通过 JSHint 检查!

命名规范

  • 文件和目录名,必须匹配/^_?[a-z0-9-]+$/,否则将被构建工具忽略。
  • 尚在开发阶段、不宜部署上线的文件,可加上-dev后缀,便于构建工具排除。
  • 首选合适的英文单词,严禁拼音首字母缩写,做到「见名识意」。
  • 命名约定:
    • 常量全大写UPPERCASE_WORD
    • 变量小驼峰camelName
    • 类名大驼峰CamelName

编码规范

  • 使用UTF-8作为文件编码格式。
  • 缩进使用 2 个空格,禁用 tab。

    Sublime Text 可以设置:

    {
      "tab_size": 2,
      "translate_tabs_to_spaces": true
    }
    
  • 尽量不要让每行超过 120 个字符,在不影响阅读的前提下,适当换行。

  • 利用(1~2个)空行分隔逻辑上相对独立的代码块,提高代码可读性与美感,同时照顾其他 review 你代码的同事的心情。

  • 行末、空行不要有空格。

    Sublime Text 可以设置:

    {
      "ensure_newline_at_eof_on_save": true,
      "trim_trailing_white_space_on_save": true
    }
    
  • 合理使用注释,写注释是为了「提高代码的可读性,从而提高代码的可维护性」,不要懒,也不要滥。Refer to 注释规范

  • 对于单 var 模式和多 var 模式,不做强行约定,但同一个文件里,风格必须一致。

    推荐有赋值的分开写,没赋值的写一块:

    var foo = 'foofoo'
    var bar = 'barbar'
    var baz, len, i
    
  • 对于分号问题,也不做强行约定,但同一个文件里,风格必须一致。

  • 尽量减少全局变量的使用。

    如果需要从 HTML 页面传入多个变量,给它们指派合适的命名空间:

    Bad:

    javascript:
      var userName = 'Steve Jobs'
      var userAge = 56
    

    Good:

    javascript:
      var user = {
        name: 'Steve Jobs',
        age: 56
      }
    

    然后将上面的user写进「edr-assets」对应项目目录内的.jshintrc中。

  • 使用 Array/Object 直接量,避免使用 Array/Object 构造器。

    Bad:

    var arr = new Array()
    var obj = new Object()
    

    Good:

    var arr = []
    var obj = {}
    
  • 语句块必须使用大括号{}

    Bad:

    if (true) return;
    

    Good:

    if (true) {
      return
    }
    
  • 大括号不换行,并与前面的小括号之间空一格。

    Bad:

    if (true)
    {
      return
    }
    
    if(true){
      return
    }
    

    Good:

    if (true) {
      return
    }
    
    function name(options) {
      options || (options = {})
    }
    
  • 操作符之间需要有 1 个空格。

    Bad:

    var x=y+z
    

    Good:

    var x = y + z
    
  • 不要为了对齐冒号,而增加多余空格。

    Bad:

    {
      foo   : 'foo',
      barbar: 'barbar'
    }
    

    Good:

    {
      foo: 'foo',
      barbar: 'barbar'
    }
    
  • 在行末使用逗号,而非行首。

    Bad:

    {
      foo: 'foo'
    , barbar: 'barbar'
    }
    

    Good:

    {
      foo: 'foo',
      barbar: 'barbar'
    }
    
  • 缓存 jQuery 对象,能复用的绝不新建。

    Bad:

    $('body').find('.foo').text('foo')
    $('body').find('.bar').text('bar')
    

    Good:

    var body = $(document.body)
    body.find('.foo').text('foo')
    body.find('.bar').text('bar')
    
  • 优先使用 jQuery 最快的 ID 选择器。

    可以配合给 HTML 标签加上js-前缀的 id,提高 DOM 操作效率。此类 id 只用于 js,不应该出现在 css 文件中。

    Bad:

    $('#js-based-id .class')
    

    Good:

    $('#js-based-id').find('.class')
    
  • 事件绑定一律使用.on()

    Bad:

    $('#js-based-id').bind('click', function(e) {
      e.preventDefault()
    })
    
    $('#js-based-id').click(function(e) {
      e.preventDefault()
    })
    

    Good:

    $('#js-based-id').on('click', function(e) {
      e.preventDefault()
    })
    
  • 同时给同一类 DOM 元素绑定事件时,利用冒泡机制,将事件绑定在公共父元素上。

    Bad:

    $('ul > li').on('click', function() {})
    

    Good:

    $('ul').on('click', 'li', function() {})
    
  • 避免频繁操作 DOM,减少重绘「Repaint」与重排「Reflow」。

    Bad:

    var ul = $('ul')
    for (var i = 0; i < 100; i++) {
      ul.append('<li>...</li>')
    }
    

    Good:

    // 方法一
    var html = ''
    for (var i = 0; i < 100; i++) {
      html += '<li>...</li>'
    }
    $('ul').html(html)
    
    // 方法二
    var fragment = document.createDocumentFragment()
    var li
    for (var i = 0; i < 100; i++) {
      li = document.createElement('li')
      fragment.appendChild(li)
    }
    $('ul').html(fragment)
    fragment = li = null
    

Sass Styleguide

Sass 只是个工具,最终还是要看编译后的 CSS 的。

命名规范

  • 文件、目录和样式名,必须匹配/^_?[a-z0-9-]+$/
  • 变量名必须匹配/^\$[a-z0-9-]+$/。Refer to _variables.scss
  • 首选合适的英文单词,严禁拼音首字母缩写,做到「见名识意」。
  • 使用.scss作为后缀名。

编码规范

  • 如无特殊说明,无须兼容 IE6。
  • 使用UTF-8作为文件编码格式。
  • 缩进使用 2 个空格,禁用 tab。
  • 每个样式块之间空一行。
  • 行末、空行不要有空格。
  • 注释使用//,禁用/* */

    Sublime Text 中,可使用快捷键Command + /快速插入、移除//

  • 左大括号前、冒号后、逗号后,均需使用 1 个空格。

    Bad:

    .selector{
      color:rgba(#000,0.5);
    }
    

    Good:

    .selector {
      color: rgba(#000, 0.5);
    }
    
  • 一行一个属性。

    Bad:

    .selector { display: block; color: rgba(#000, 0.5); }
    

    Good:

    .selector {
      display: block;
      color: rgba(#000, 0.5);
    }
    
  • 简写属性值。

    Bad:

    .selector {
      margin: 10px auto 20px auto;
      padding: 0 20px 0;
      border-width: 1px;
      border-style: solid;
      border-color: #000;
    }
    

    Good:

    .selector {
      margin: 10px auto 20px;
      padding: 0 20px;
      border: 1px solid #000;
    }
    
  • 属性值为0时省略单位。

    Bad:

    .selector {
      border: 0px;
    }
    

    Good:

    .selector {
      border: 0;
    }
    
  • 嵌套尽量不要超过 4 层。

    对于这样的 HTML 结构:

    <nav class="nav">
      <ul>
        <li>
          <a href=""></a>
        </li>
      </ul>
    </nav>
    

    Bad:

    .nav {
      ul {
        li {
          a {
            &:hover {}
          }
        }
      }
    }
    

    Good:

    .nav {
      li {}
    
      a {
        &:hover {}
      }
    }
    
  • 对于像.active.selected.required等比较通用的、表示状态的名称,需限定作用域。

    Good:

    .nav {
      a.active {}
    }
    
    .aside {
      a.active {}
    }
    
  • 尽量使用类选择器,如果必须使用 id 选择器,避免嵌套。

    Bad:

    #header .search #quicksearch {}
    
  • 使用path()代替原生的url()和 Compass 的image-url()。Refer to Path.md

    Good:

    .selector {
      background-image: path('ninja.png');
    }
    

Mixins

Placeholder Selectors

Helper Classes

UI Components

Buttons

Link Link

= link_to 'Link', '#', class: 'btn'
# <a href="#" class="btn">Link</a>

= button_tag
# <button type="button" class="btn">Button</button>

= button_tag 'Primary', class: 'btn-primary', disabled: true
# <button type="button" class="btn btn-primary" disabled="disabled">Primary</button>

Forms

密码长度应在 6 位以上,并使用数字、字母和符号的组合

= form_tag '/', autocomplete: 'off'
  .form-item
    = label_tag :email, '邮箱', class: 'heading-label required'
    = text_field_tag :email

  .form-item
    = label_tag :password, '密码', class: 'heading-label required'
    = password_field_tag :password
    p.tips 密码长度应在 6 位以上,并使用数字、字母和符号的组合

  .form-item
    = label_tag :weibo, '微博', class: 'heading-label'
    = text_area_tag :weibo, nil, rows: 3, placeholder: '有什么新鲜事想告诉大家?'

  .form-item
    = check_box_tag :remember
    = label_tag :remember, '15天内自动登录', class: 'linking-label'

  .form-item
    = submit_tag

Flash Messages

Well done!

Sorry, something went wrong!

Warning!

Attention!

# Controller:
flash[:success] = :default
flash[:error] = :default
flash[:warn] = :default
flash[:info] = :default

# View:
= flash_message

Slim Styleguide

注意,你写的仍然是 HTML,所以,语义!

命名规范

  • 文件和目录名,必须匹配/^[a-z0-9_-]+$/
  • 首选合适的英文单词,严禁拼音首字母缩写,做到「见名识意」。

编码规范

  • 使用UTF-8作为文件编码格式。
  • 缩进使用 2 个空格,禁用 tab。
  • 利用(1~2个)空行分隔逻辑上相对独立的代码块,提高代码可读性与美感,同时照顾其他 review 你代码的同事的心情。
  • 行末、空行不要有空格。
  • 使用doctype 5声明文档类型。

    doctype 5
    html
      head
        meta charset='utf-8'
      body
    
  • css 放页面head区,js 放页面body区底部。

    - content_for :headers do
      = stylesheet_link_tag 'foo'.path, 'bar'.path
    
    - content_for :footers do
      = seajs_use 'foo', 'bar'
    

    content_for 代码块不要随意放置,一律放在 Slim 文件底部。

  • 慎用==#{{ }},避免遭受 XSS 攻击。

    主要是在处理用户输入的不可控内容时需要特别注意。

    = '<script>alert("XSS!")</script>'
    # &lt;script&gt;alert(&quot;XSS!&quot;)&lt;/script&gt;
    
    == '<script>alert("XSS!")</script>'
    # <script>alert("XSS!")</script>
    
  • 为了可读性,内联标签的属性需使用括号包裹。

    Bad:

    ul
      li.first : a href='/a' A link
      li : a href='/b' B link
    

    Good:

    ul
      li.first : a[href='/a'] A link
      li : a[href='/b'] B link
    
  • 如果父、子标签都包含属性,需换行,弃用内联。

    Bad:

    p class=['foo', 'bar'] : a(href='/a') A link
    

    Good:

    p class=['foo', 'bar']
      a href='/a' A link
    
  • 使用#id.class时勿加div,因为它是默认的。

    Bad:

    div#nav
    div.form-item
    

    Good:

    #nav
    .form-item
    
  • 标签的属性值可直接传入 Ruby 代码,切勿画蛇添足。

    Bad:

    a href='#{new_user_path}' Create User
    

    Good:

    a href=new_user_path Create User
    
  • 对于是直接写 HTML 还是使用 Helper,不做强行约定,简洁、可读性高即可。

    = link_to 'A link', '/a', class: 'foo'
    
    a.foo href='/a' A link
    
  • 表单元素,推荐使用 Helper。

    = form_tag '/', autocomplete: 'off'
      = label_tag
      = password_field_tag
      = submit_tag
    
  • Ruby 代码中的 Hash,推荐使用新的风格。

    # New:
    = text_field_tag :email, placeholder: 'Enter email', data: { k1: 'v1', k2: 'v2' }
    
    # Old:
    = text_field_tag :email, :placeholder => 'Enter email', :data => { :k1 => 'v1', :k2 => 'v2' }
    

Custom Helpers

Refer to Helpers.md.