前端开发规范

302 阅读15分钟

前端开发规范

前端代码规范

  • 总体规范

    1、格式化代码,格式化代码,格式化代码;
    
    2、尽量降低代码的复杂度,单一职责,提炼函数;
    
    3、缩进使用soft tab(4个空格);
    
    4、文件最后保留一个空行;
    
    5、所有常量放在 constants.js 中,必须添加注释;各模块的,各类型的常量最好抽成单独文件(例如,urls.constants.js),然后再通过 constants.js 去引用,不能直接引用;
    
    6、if判断不超过两层,否则要抽取出来;for 循环尽量不要超过三层;
    
    7、页面之间传递数据,要遵循规律,写好注释,方便查找和维护;
    
    8、所有公共方法、工具函数要抽取出来要放在 common 中;
    
    9、一些常用功能,例如 http 请求、弹窗提示、查看大图、拍照、选图、上传文件、扫码、地图等功能,不能直接调用,要封装成自己的组件后再调用;
    
    10、环境切换等一些项目配置,要通过 config 文件去配置;
        
    11、html 中要尽量避免使用 style 属性;
    
    12、调用原生能力时,一定要先判断当前设备环境,浏览器环境中调用时不能报错;
    
    13、页面之间返回时要遵循从哪来回哪去原则,要使用的框架的返回方法,不能使用跳到新页面的方式来返回,特定业务场景除外;
    
    14、需要更改公共组件时要通知项目负责人,由负责人通知全体开发人员;
    
    15、废弃代码要及时删除,避免出现无用空行,减少不必要的注释,保持代码整洁;
    
    16、静态资源文件要按照功能模块分类,不能都堆放到一个目录下;
    
    17、文件、资源文件、变量、函数等命名要有实际意义,具有可读性,禁止使用中文命名;
    
    18、log 要封装到公共方法,避免直接使用 console 打印日志;
    
    19、js 中要使用单引号; 
    
    20、使用 TypeScript 时,出参入参要使用 interface.dto.ts 进行 类型断言;    
    ...
    
  • 格式化代码

    使用 eslint/jslinet/tslinet  进行代码格式化。
    
    编写完代码后请格式化代码。
    
    vscode 快捷键:shift + alt + f
    
    idea/webstorm 快捷键:command + alt + l
    
  • 命名规范

    • 项目命名
    全部采用小写方式,以中划线分隔。
    
    例:my-project-name
    
    • 目录命名
    全部采用小写方式,以中划线分隔;有复数结构时,要采用复数命名法。
    
    例:pages, assets, directives, components, mixins, utils, constants, my-dir-name
    
    • javaScript 文件命名
    全部采用小写方式,以中划线分隔。
    
    例:file-name.js, file-name.dto.js, file-name.controller.js,  file-name.module.js, file-name.service.js
    
    • typeScript 文件命名
    全部采用小写方式,以中划线分隔。
    
    例:file-name.ts
    
    • css, scss, sass, less 文件命名
    全部采用小写方式,以中划线分隔。
    
    例:file-name.css, file-name.scss, file-name.sass, file-name.less
    
    • html 文件命名
    全部采用小写方式,以中划线分隔。
    
    例:file-name.html
    
    • 组件 component 命名
    全部采用小写方式,以中划线分隔。
    
    例:file-name.vue
    
  • JavaScript 规范

    • 文件信息
        每个文件头部要注释文件信息:创建时间、创建人,也可以备注下该文件负责的功能信息;
    
    /**
     * 用来存放常量    
     * Created by xxx on 2222/22/22.
     */
    
    • 分号
        行代码结束后添加 ; ;
    
    • 添加空格
    1、二元运算符前后
    
    2、三元运算符'?:'前后
    
    3、代码块'{'前
    
    4、下列关键字前:else, while, catch, finally
    
    5、下列关键字后:if, else, for, while, do, switch, case, try,catch, finally, with, return, typeof
    
    6、单行注释'//'后(若单行注释和代码同行,则'//'前也需要),多行注释'*'后
    
    7、对象的属性值前
    
    8、for循环,分号后留有一个空格,前置条件如果有多个,逗号后留一个空格
    
    9、无论是函数声明还是函数表达式,'{'前一定要有空格
    
    10、函数的参数之间
    
    • 空行
       1、变量声明后(当变量声明在代码块的最后一行时,则无需空行)
       
       2、注释前(当注释在代码块的第一行时,则无需空行)
       
       3、代码块后(在函数调用、数组、对象中则无需空行)
       
       4、文件最后保留一个空行
    
    • 分号
        行代码结束后添加 ';'
    • 换行
    换行的地方,行末必须有 ',' 或者运算符;
    
    以下几种情况不需要换行:
    
        下列关键字后:else, catch, finally
        代码块 '{' 前
    
    以下几种情况需要换行:
    
        代码块 '{' 后和 '}' 前
        变量赋值后
    
    • 单行注释
    双斜线后,必须跟一个空格;
    
    缩进与下一行代码保持一致;
    
    可位于一个代码行的末尾,与代码间隔一个空格。
    
    if (condition) {
        // if you made it here, then all security checks passed
        allowed();
    }
    
    var zhangsan = 'zhangsan'; // one space after code
    
    
    • 多行注释
    最少三行, '*'后跟一个空格,具体参照右边的写法;
    
    建议每个 function 都要进行注释;
    
    以下情况下必须使用:
    
        难于理解的代码段;
        工具函数,公共方法;
        可能存在错误的代码段;
        浏览器特殊的HACK代码;
        业务逻辑强相关的代码。
    
    /*
     * one space after '*'
     */
    var x = 1;
    
    • 文档注释
    各类标签@param, @method等请参考usejsdoc和JSDoc Guide;
    
    建议在以下情况下使用:
    
        所有常量;
        所有函数;
        所有类;
    
    /**
     * @func
     * @desc 一个带参数的函数
     * @param {string} a - 参数a
     * @param {number} b=1 - 参数b默认值为1
     * @param {string} c=1 - 参数c有两种支持的取值</br>1—表示x</br>2—表示xx
     * @param {object} d - 参数d为一个对象
     * @param {string} d.e - 参数d的e属性
     * @param {string} d.f - 参数d的f属性
     * @param {object[]} g - 参数g为一个对象数组
     * @param {string} g.h - 参数g数组中一项的h属性
     * @param {string} g.i - 参数g数组中一项的i属性
     * @param {string} [j] - 参数j是一个可选参数
     * @return {boolean}
     */
    function foo(a, b, c, d, g, j) {
        ...
        return true;
    }
    
    • 引号
    最外层统一使用单引号。
    
    // not good
    var x = "test";
    
    // good
    var y = 'foo',
        z = '<div id="test"></div>';
    
    • 变量命名
    1、标准变量采用小驼峰式命名法(除了对象的属性外,主要是考虑到接口返回的数据,但尽量也要用);
    
    4、'Android'在变量名中大写第一个字母;'iOS'在变量名中小写第一个,大写后两个字母;
    
    5、常量全大写,用下划线连接;
    
    6、构造函数采用大驼峰式命名法;
    
    var thisIsMyName;
    var goodID;
    var reportURL;
    var AndroidVersion;
    var iOSVersion;
    var MAX_COUNT = 10;
    
    function Person(name) {
        this.name = name;
    }
    
    function myFun(name) {
        ...
    }
    
    • 数组、对象
    对象属性名不需要加引号;
    
    对象以缩进的形式书写,不要写在一行;
    
    • null
    适用场景:
    
        初始化一个将来可能被赋值为对象的变量;
        与已经初始化的变量做比较;
        作为一个参数为对象的函数的调用传参;
        作为一个返回对象的函数的返回值;
    
    不适用场景:
    
        不要用null来判断函数调用时有无传参;
        不要与未初始化的变量做比较;
    
    • undefined
    永远不要直接使用 undefined 进行变量判断;
    
    使用 typeof 和字符串 'undefined' 对变量进行判断。
    
    // not good
    if (undefined === person) {
        ...
    }
    
    // good
    if ('undefined' === typeof person) {
        ...
    }
    
    • 其它
    获取对象属性时要先判断对象一定存在,遍历数组时,要先确定数组存在,并且是个数组;
    尽量用'=', '!'代替'`', '!='for-in 里一定要有 hasOwnProperty 的判断;
    不要在内置对象的原型上添加方法,如Array, Date;
    不要在内层作用域的代码里声明了变量,之后却访问到了外层作用域的同名变量;
    变量不要先使用后声明;
    不要在一句代码中单单使用构造函数,记得将其赋值给某个变量;
    不要在同个作用域下声明同名变量;
    不要在一些不需要的地方加括号,例:delete(a.b);
    不要使用未声明的变量(全局变量需要加到.jshintrc文件的globals属性里面);
    不要声明了变量却不使用;
    不要在应该做比较的地方做赋值;
    debugger不要出现在提交的代码里;
    数组中不要存在空元素;
    不要在循环内部声明函数;
    不要像这样使用构造函数,例:new function () { ... }, new Object;
    对上下文this的引用只能使用'_this', 'that', 'self'其中一个来命名;
    行尾不要有空白字符;
    switch的falling through和no default的情况一定要有注释特别说明;
    不允许有空的代码块。
    
  • HTML 5 规范

    CodeGuide 参考地址

    • 语法
    1、缩进使用soft tab(4个空格);
    
    2、嵌套的节点应该缩进;
    
    3、在属性上,使用双引号,不要使用单引号;
    
    4、属性名全小写,用中划线做分隔符;
    
    5、不要在自动闭合标签结尾处使用斜线(HTML5 规范 指出他们是可选的);
    
    6、不要忽略可选的关闭标签;
    
    7、尽量遵循HTML标准和语义,但是不应该以浪费实用性作为代价;
      
    8、任何时候都要用尽量小的复杂度和尽量少的标签来解决问题。
    
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>title</title>
        </head>
      	<link rel="stylesheet" href="style.css">
    	<script src="script.js"></script>
        <body>
            <div></div>
            <input disabled>
            <img src="images/img.png">
            <h1 class="hello-world">Hello, world!</h1>
        </body>
    </html>
    
    • 属性顺序
    属性应该按照特定的顺序出现以保证易读性
    
    (1)class
    (2)id
    (3)name
    (4)data-*
    (5)src, for, type, href, value , max-length, max, min, pattern
    (6)placeholder, title, alt
    (7)aria-*, role
    (8)required, readonly, disabled
    
    class是为高可复用组件设计的,所以应处在第一位;
    id 具体且应该尽量少使用,所以将它放在第二位。
    
    • 减少标签数量
    在编写HTML代码时,需要尽量避免多余的父节点;
    
    <!-- 不建议这么做 -->
    <span class="avatar">
        <img src="...">
    </span>
    
    <!-- 建议这么做 -->
    <img class="avatar" src="...">
    
    • JavaScript 生成的标签
    通过 JavaScript 生成的Î标签让内容变得更难查找,更难编辑,性能更差。应该尽量避免这种情况的出现。
    
  • css、less、sass、scss

    1、每个属性声明末尾都要加分号;
    
    2、类名使用小写字母,以中划线分隔;
    
    3、id 采用全大写下滑线式命名;
    
    4、less、sass、scss 中的变量、函数以中划线分隔命名;
    
    5、相关的属性声明按右边的顺序做分组处理,组之间需要有一个空行;
    
    6、尽量避免使用 !important 。
    
    • 书写顺序前后
    (1)定位属性:position  display  float  left  top  right  bottom   overflow  clear   z-index
    (2)自身属性:width  height  padding  border  margin   background
    (3)文字样式:font-family   font-size   font-style   font-weight   font-varient   color
    (4)文本属性text-align   vertical-align   text-wrap   text-transform   text-indent    text-decoration   letter-spacing    word-spacing    white-space   text-overflow
    
    目的:减少浏览器reflow(回流),提升浏览器渲染dom的性能。
    
    // 下面是推荐的属性的顺序
    [
        [
            "display",
            "visibility",
            "float",
            "clear",
            "overflow",
            "overflow-x",
            "overflow-y",
            "clip",
            "zoom"
        ],
        [
            "table-layout",
            "empty-cells",
            "caption-side",
            "border-spacing",
            "border-collapse",
            "list-style",
            "list-style-position",
            "list-style-type",
            "list-style-image"
        ],
        [
            "-webkit-box-orient",
            "-webkit-box-direction",
            "-webkit-box-decoration-break",
            "-webkit-box-pack",
            "-webkit-box-align",
            "-webkit-box-flex"
        ],
        [
            "position",
            "top",
            "right",
            "bottom",
            "left",
            "z-index"
        ],
        [
            "margin",
            "margin-top",
            "margin-right",
            "margin-bottom",
            "margin-left",
            "-webkit-box-sizing",
            "-moz-box-sizing",
            "box-sizing",
            "border",
            "border-width",
            "border-style",
            "border-color",
            "border-top",
            "border-top-width",
            "border-top-style",
            "border-top-color",
            "border-right",
            "border-right-width",
            "border-right-style",
            "border-right-color",
            "border-bottom",
            "border-bottom-width",
            "border-bottom-style",
            "border-bottom-color",
            "border-left",
            "border-left-width",
            "border-left-style",
            "border-left-color",
            "-webkit-border-radius",
            "-moz-border-radius",
            "border-radius",
            "-webkit-border-top-left-radius",
            "-moz-border-radius-topleft",
            "border-top-left-radius",
            "-webkit-border-top-right-radius",
            "-moz-border-radius-topright",
            "border-top-right-radius",
            "-webkit-border-bottom-right-radius",
            "-moz-border-radius-bottomright",
            "border-bottom-right-radius",
            "-webkit-border-bottom-left-radius",
            "-moz-border-radius-bottomleft",
            "border-bottom-left-radius",
            "-webkit-border-image",
            "-moz-border-image",
            "-o-border-image",
            "border-image",
            "-webkit-border-image-source",
            "-moz-border-image-source",
            "-o-border-image-source",
            "border-image-source",
            "-webkit-border-image-slice",
            "-moz-border-image-slice",
            "-o-border-image-slice",
            "border-image-slice",
            "-webkit-border-image-width",
            "-moz-border-image-width",
            "-o-border-image-width",
            "border-image-width",
            "-webkit-border-image-outset",
            "-moz-border-image-outset",
            "-o-border-image-outset",
            "border-image-outset",
            "-webkit-border-image-repeat",
            "-moz-border-image-repeat",
            "-o-border-image-repeat",
            "border-image-repeat",
            "padding",
            "padding-top",
            "padding-right",
            "padding-bottom",
            "padding-left",
            "width",
            "min-width",
            "max-width",
            "height",
            "min-height",
            "max-height"
        ],
        [
            "font",
            "font-family",
            "font-size",
            "font-weight",
            "font-style",
            "font-variant",
            "font-size-adjust",
            "font-stretch",
            "font-effect",
            "font-emphasize",
            "font-emphasize-position",
            "font-emphasize-style",
            "font-smooth",
            "line-height",
            "text-align",
            "-webkit-text-align-last",
            "-moz-text-align-last",
            "-ms-text-align-last",
            "text-align-last",
            "vertical-align",
            "white-space",
            "text-decoration",
            "text-emphasis",
            "text-emphasis-color",
            "text-emphasis-style",
            "text-emphasis-position",
            "text-indent",
            "-ms-text-justify",
            "text-justify",
            "letter-spacing",
            "word-spacing",
            "-ms-writing-mode",
            "text-outline",
            "text-transform",
            "text-wrap",
            "-ms-text-overflow",
            "text-overflow",
            "text-overflow-ellipsis",
            "text-overflow-mode",
            "-ms-word-wrap",
            "word-wrap",
            "-ms-word-break",
            "word-break"
        ],
        [
            "color",
            "background",
            "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader",
            "background-color",
            "background-image",
            "background-repeat",
            "background-attachment",
            "background-position",
            "-ms-background-position-x",
            "background-position-x",
            "-ms-background-position-y",
            "background-position-y",
            "-webkit-background-clip",
            "-moz-background-clip",
            "background-clip",
            "background-origin",
            "-webkit-background-size",
            "-moz-background-size",
            "-o-background-size",
            "background-size"
        ],
        [
            "outline",
            "outline-width",
            "outline-style",
            "outline-color",
            "outline-offset",
            "opacity",
            "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity",
            "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha",
            "-ms-interpolation-mode",
            "-webkit-box-shadow",
            "-moz-box-shadow",
            "box-shadow",
            "filter:progid:DXImageTransform.Microsoft.gradient",
            "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient",
            "text-shadow"
        ],
        [
            "-webkit-transition",
            "-moz-transition",
            "-ms-transition",
            "-o-transition",
            "transition",
            "-webkit-transition-delay",
            "-moz-transition-delay",
            "-ms-transition-delay",
            "-o-transition-delay",
            "transition-delay",
            "-webkit-transition-timing-function",
            "-moz-transition-timing-function",
            "-ms-transition-timing-function",
            "-o-transition-timing-function",
            "transition-timing-function",
            "-webkit-transition-duration",
            "-moz-transition-duration",
            "-ms-transition-duration",
            "-o-transition-duration",
            "transition-duration",
            "-webkit-transition-property",
            "-moz-transition-property",
            "-ms-transition-property",
            "-o-transition-property",
            "transition-property",
            "-webkit-transform",
            "-moz-transform",
            "-ms-transform",
            "-o-transform",
            "transform",
            "-webkit-transform-origin",
            "-moz-transform-origin",
            "-ms-transform-origin",
            "-o-transform-origin",
            "transform-origin",
            "-webkit-animation",
            "-moz-animation",
            "-ms-animation",
            "-o-animation",
            "animation",
            "-webkit-animation-name",
            "-moz-animation-name",
            "-ms-animation-name",
            "-o-animation-name",
            "animation-name",
            "-webkit-animation-duration",
            "-moz-animation-duration",
            "-ms-animation-duration",
            "-o-animation-duration",
            "animation-duration",
            "-webkit-animation-play-state",
            "-moz-animation-play-state",
            "-ms-animation-play-state",
            "-o-animation-play-state",
            "animation-play-state",
            "-webkit-animation-timing-function",
            "-moz-animation-timing-function",
            "-ms-animation-timing-function",
            "-o-animation-timing-function",
            "animation-timing-function",
            "-webkit-animation-delay",
            "-moz-animation-delay",
            "-ms-animation-delay",
            "-o-animation-delay",
            "animation-delay",
            "-webkit-animation-iteration-count",
            "-moz-animation-iteration-count",
            "-ms-animation-iteration-count",
            "-o-animation-iteration-count",
            "animation-iteration-count",
            "-webkit-animation-direction",
            "-moz-animation-direction",
            "-ms-animation-direction",
            "-o-animation-direction",
            "animation-direction"
        ],
        [
            "content",
            "quotes",
            "counter-reset",
            "counter-increment",
            "resize",
            "cursor",
            "-webkit-user-select",
            "-moz-user-select",
            "-ms-user-select",
            "user-select",
            "nav-index",
            "nav-up",
            "nav-right",
            "nav-down",
            "nav-left",
            "-moz-tab-size",
            "-o-tab-size",
            "tab-size",
            "-webkit-hyphens",
            "-moz-hyphens",
            "hyphens",
            "pointer-events"
        ]
    ]
    
    
    • 属性简写
    常见的属性简写包括:font、background、transition、animation 。
    
    • 颜色
    颜色16进制用小写字母,颜色16进制尽量用简写。
    
    例: #abcdef
    
    • 媒体查询
    尽量将媒体查询的规则靠近与他们相关的规则,不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部,这样做只会让大家以后更容易忘记他们。
    
    • 媒体查询
    尽量将媒体查询的规则靠近与他们相关的规则,不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部,这样做只会让大家以后更容易忘记他们。
    
    • 媒体查询
    尽量将媒体查询的规则靠近与他们相关的规则,不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部,这样做只会让大家以后更容易忘记他们。
    

Git 规范

  • 分支

    1、master 分支为主分支(保护分支),不能直接在master上进行修改代码和提交;master分支对应线上版本。
    
    2、dev 分支为测试分支,所以开发完成需要提交测试的功能合并到该分支;dev分支对应开发版本。
    
    3、master、release、dev 分支只能由开发组长合并及提交,其余人员需要在各自分支上进行开发工作。
    
    4、task/bug 分支为开发分支,大家根据tapd 不同的任务 ID 创建独立的功能分支,开发完成后合并到dev分支。
    
    5、git提交尽量遵循单次提交的代码是对一个完整但是影响尽量小的功能的修改,不要把对几个功能的修改混在一起提交。
    
    6、注释最少应该写清楚本次做的修改和达到的效果,越详细越好(最好是任务名称 + 任务说明)。
    
    7、分支一定要从 master 的最新 tag 拉出(除非有特殊要求),分支名字必须有明确的含义,以方便管理。
    
    8、功能上线后,对应的分支应该及时删除。
    
    9、分支名字的命名方法为:task 或 bug 开头,加 tapd 任务ID,示例:task/ID1018393 。
    
    10、没有 tapd task/bug ID 的,请找相关人员去创建 task 或 bug,特殊的使用特殊分支,示例:bug/999999 。
    
    11、不要直接往 release 提交功能代码,release 代码更新来源应该是 dev 。
      
    12、不要直接往 dev 提交功能代码,dev 代码更新来源应该是其他分支。
    
    13、分支不能重复使用,分支与分支之间不能相互合并(多人开发同一模块,需要共享代码时,拉出来的功能性主分支除外)。
    
    14、同一个任务多次提交时尽量使用 rebase 合并 commit ,减少push次数,方便查看提交记录。
    
  • 提交 commit 信息

    1、git commit 注释信息的第一行必须以小写 task/bug ,加tapd 上对应的 task/bug 号(也就是分支名开头),后面写详细内容。
    
    2、请避免不写注释直接提交。
    
    3、示例:task/ID1018393 【app】【模块】【子模块】详细内容... 。
    
  • 注意

    请先配置本地 git 信息
    
        $ git config --global user.name "张三"
        $ git config --global user.email "eamil@qq.com"
        
    name 一定是开发者的中文姓名,方便查看和管理。
    
如果大家有更好的规范建议,欢迎随时补充。