基于 Vue 的前端开发规范

作者: 后除 | 来源:发表于2018-07-01 23:07 被阅读106次

    一、框架 / Vue

    1.组件名

    组件名为多个单词,并且用连接线(-)连接,避免与 HTML 标签冲突,并且结构更加清晰。

    示例:

    // 反例
    export default {
        name: 'item'
    }
    
    // 正例
    export default {
        name: 'page-article-item'
    }
    

    2.组件文件

    组件的名字应该始终是以连接线(-)连接的单词,一方面可与组件名一致,使项目更加清晰,另一方面这样的写法对编辑器引入也很友好。

    示例:

    // 反例
    ├── index.html
    ├── main.js
    └── components
        ├── pageheader
        ├── pagearticle
        └── pageheader
    
    // 正例
    ├── index.html
    ├── main.js
    └── components
        ├── page-header
        ├── page-article
        └── page-header
    

    对于例如按钮、下拉框或表格这样的基础组件应该始终以一个特定的前缀开头,区别与其他业务组件。

    示例:

    // 反例
    ├── index.html
    ├── main.js
    └── components
        ├── page-header
        ├── page-article
        ├── page-header
        ├── mazey-button
        ├── mazey-select
        └── mazey-table
    
    // 正例
    ├── index.html
    ├── main.js
    └── components
    |   ├── page-header
    |   ├── page-article
    |   └── page-header
    └── base
        ├── mazey-button
        ├── mazey-select
        └── mazey-table
    

    3.Prop

    定义 Prop 的时候应该始终以驼峰格式(camelCase)命名,在父组件赋值的时候使用连接线(-)。这里遵循每个语言的特性,因为在 HTML 标记中对大小写是不敏感的,使用连接线更加友好;而在 JavaScript 中更自然的是驼峰命名。

    示例:

    // 反例
    // Vue
    props: {
        article-status: Boolean
    }
    // HTML
    <article-item :articleStatus="true"></article-item>
    
    // 正例
    // Vue
    props: {
        articleStatus: Boolean
    }
    // HTML
    <article-item :article-status="true"></article-item>
    

    Prop 的定义应该尽量详细的指定其类型、默认值和验证。

    示例:

    // 反例
    props: ['attrM', 'attrA', 'attrZ']
    
    // 正例
    props: {
        attrM: Number,
        attrA: {
            type: String,
            required: true
        },
        attrZ: {
            type: Object,
            // 数组/对象的默认值应该由一个工厂函数返回
            default: function () {
                return {
                    msg: '成就你我'
                }
            }
        },
        attrE: {
            type: String,
            validator: function (v) {
                return !(['success', 'fail'].indexOf(v) === -1) 
            }
        }
    }
    

    4.v-for

    在执行 v-for 遍历的时候,总是应该带上 key 值使更新 DOM 时渲染效率更高。

    示例:

    // 反例
    <ul>
        <li v-for="item in list">
            {{ item.title }}
        </li>
    </ul>
    
    // 正例
    <ul>
        <li v-for="item in list" :key="item.id">
            {{ item.title }}
        </li>
    </ul>
    

    v-for 应该避免与 v-if 在同一个元素(例如:<li>)上使用,因为 v-for 的优先级比 v-if 更高,为了避免无效计算和渲染,应该尽量将 v-if 放到容器的父元素之上。

    示例:

    // 反例
    <ul>
        <li v-for="item in list" :key="item.id" v-if="showList">
            {{ item.title }}
        </li>
    </ul>
    
    // 正例
    <ul v-if="showList">
        <li v-for="item in list" :key="item.id">
            {{ item.title }}
        </li>
    </ul>
    

    5.v-if / v-else-if / v-else

    若同一组 v-if 逻辑控制中的元素逻辑相同,Vue 为了更高效的元素切换,会复用相同的部分,例如:value。为了避免复用带来的不合理效果,应该在同种元素上加上 key 做标识。

    示例:

    // 反例
    <div v-if="hasData">
        <span>{{ mazeyData }}</span>
    </div>
    <div v-else>
        <span>无数据</span>
    </div>
    
    // 正例
    <div v-if="hasData" key="mazey-data">
        <span>{{ mazeyData }}</span>
    </div>
    <div v-else key="mazey-none">
        <span>无数据</span>
    </div>
    

    6.指令缩写

    为了统一规范始终使用指令缩写,使用v-bindv-on并没有什么不好,这里仅为了统一规范。

    示例:

    <input :value="mazeyUser" @click="verifyUser">
    

    7.样式

    为了避免样式冲突,整个项目要么全都使用 scoped 特性,要么使用 BEM 约定。

    示例:

    // 反例
    <template>
        <button class="btn btn-sure">确认</button>
    </template>
    <style>
        .btn{
            border: 1px solid #F1F1F1;
        }
        .btn-sure{
            background-color: blue;
        }
    </style>
    
    // 正例
    <!-- 使用 scoped 特性 -->
    <template>
        <button class="btn btn-sure">确认</button>
    </template>
    <style scoped>
        .btn{
            border: 1px solid #F1F1F1;
        }
        .btn-sure{
            background-color: blue;
        }
    </style>
    
    <!-- 使用 BEM(Block Element Modifier) 特性 -->
    <template>
        <button class="menu-btn menu-btn-sure">确认</button>
    </template>
    <style>
        .menu-btn{
            border: 1px solid #F1F1F1;
        }
        .menu-btn-sure{
            background-color: blue;
        }
    </style>
    

    注意

    不建议使用类似于 font-size-20color-666margin-top-20这样的类,此时如果想把全局的color-666颜色改成 #ccc,不管是直接把 .color-666{color: #666;} 改成 .color-666{color: #ccc;},还是 全局搜索修改 class 名都很麻烦。本质上我认为 color-666 和直接写 style="color: #666;" 并没有区别。

    8.单文件组件的顶级元素顺序

    为了统一和便于阅读,应该按 <template><script><style>的顺序放置。

    示例:

    // 反例
    <style>
    /* CSS */
    </style>
    <script>
    /* JavaScript */
    </script>
    <template>
    <!-- HTML -->
    </template>
    
    // 正例
    <template>
    <!-- HTML -->
    </template>
    <script>
    /* JavaScript */
    </script>
    <style>
    /* CSS */
    </style>
    

    二、JavaScript

    1.var / let / const

    建议不再使用 var,而使用 let / const,优先使用 const。任何一个变量的使用都要提前申明,除了 function 定义的函数可以随便放在任何位置。

    2.引号

    建议不再使用双引号,静态字符串使用单引号,动态字符串使用反引号衔接。

    示例:

    // 反例
    const foo = "后除"
    const bar = foo + ",前端工程师"
    
    // 正例
    const foo = '后除'
    const bar = `${foo},前端工程师`
    

    3.函数

    匿名函数统一使用箭头函数,多个参数/返回值时优先使用对象的结构赋值。

    示例:

    // 反例
    function getPersonInfo (name, sex) {
        // ...
        return [name, gender]
    }
    
    // 正例
    function getPersonInfo ({name, sex}) {
        // ...
        return {name, gender}
    }
    

    函数名统一使用驼峰命名,以大写字母开头申明的都是构造函数,使用小写字母开头的都是普通函数,也不该使用 new 操作符去操作普通函数。

    4.对象

    建议使用扩展运算符拷贝对象而不是 Object.assign(target, ...sources)

    示例:

    // 错误
    const foo = {a: 0, b: 1}
    const bar = Object.assign(foo, {c: 2})
    
    // 反例
    const foo = {a: 0, b: 1}
    const bar = Object.assign({}, foo)
    
    // 正例
    const foo = {a: 0, b: 1}
    const bar = JSON.parse(JSON.stringify(foo))
    
    // 极好
    const foo = {a: 0, b: 1}
    const bar = {...foo, c: 2}
    

    对象尽量静态化,添加新属性使用 Object.assign(target, ...sources)

    示例:

    // 反例
    const foo = {a: 3}
    foo.b = 4
    
    // 正例
    const foo = {a: 3}
    Object.assign(foo, {b: 4})
    

    若有遍历对象的需求,优先使用 Map 结构。

    示例:

    // 反例
    const myMap = {
        foo: 0,
        bar: 1
    }
    for (let key in myMap) {
        // ...
    }
    
    // 正例
    const myMap = new Map([])
    for (let [key, value] of myMap.entries()) {
        // ...
    }
    

    5.模块

    统一使用 import / export 的方式管理项目的模块。

    示例:

    // lib.js
    export default {}
    
    // app.js
    import app from './lib'
    

    import 统一放在文件顶部。

    如果模块只有一个输出值,使用 export default,否则不用。

    6.循环

    for (var i = 0; i < arr.length; i++) {} 这样的方式遍历不是很好,尤其当 arr 是 Dom 对象的时候,这样就会一直在访问 Dom 层,访问 Dom 层的代价是很大的。for (var i = 0, j=arr.length; i < j; i++) {} 这样的方式去用循环是比较好的,只会访问一次 Dom 层(不适用于 Dom 节点会动态更新的场景)。

    7.eval

    避免使用 eval,如要进行字符串转化为对象,最好使用浏览器的内置方法来解析 JSON 数据,以确保代码的安全性和数据的合法性。如果浏览器不支持 JSON.parse(),你可以使用 JSON.org 所提供的库。如果不得不使用 eval(),可以尝试用 new Function() 来代替,在 new Function() 中运行的代码会在一个局部函数作用域内执行,因此源码中定义的变量不会自动变成全局变量。

    三、HTML / CSS

    1.标签

    在引用外部 CSS 或 JavaScript 时不写 type 属性。HTML5 默认 type 为 text/csstext/javascript 属性,所以没必要指定。

    示例:

    // 反例
    <link rel="stylesheet" href="//www.test.com/css/test.css" type="text/css">
    <script src="//www.test.com/js/test.js" type="text/javascript"></script>
    
    // 正例
    <link rel="stylesheet" href="//www.test.com/css/test.css">
    <script src="//www.test.com/js/test.js"></script>
    

    2.协议

    省略协议头部声明,例如:http:https:,且不加引号。

    示例:

    // 反例
    background: url("http://www.test.com/img/test.png");
    
    // 正例
    background: url(//www.test.com/img/test.png);
    

    3.选择器

    选择器尽可能简单,能使用 .test 别使用 div.test

    每个选择器和声明都要独立新行。

    示例:

    // 反例
    p.test{
        color: #000;
    }
    h1,h2,h3{
        font-size: 12px;
        color: #666;
    }
    
    // 正例
    .test{
        color: #000;
    }
    h1,
    h2,
    h3{
        font-size: 12px;
        color: #666;
    }
    

    4.分号

    每个声明最后都要加分号 ;,即使是最后一个。

    示例:

    // 反例
    h3{
        font-size: 12px;
        color: #666
    }
    
    // 正例
    h3{
        font-size: 12px;
        color: #666;
    }
    

    5.命名

    Class 和 ID 的命名应该语义化,通过看名字就知道是干嘛的;多个单词用连接线 - 连接。

    示例:

    // 反例
    .testheader{
        font-size: 20px;
    }
    
    // 正例
    .test-header{
        font-size: 20px;
    }
    

    6.属性缩写

    CSS 属性尽量使用缩写,提高代码的效率和方便理解。

    示例:

    // 反例
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    
    // 正例
    border: 1px solid #ccc;
    

    7.文档类型

    应该总是使用 HTML5 标准。

    示例:

    <!DOCTYPE html>
    

    8.table

    应该避免使用 table 做页面布局,因为同样的布局使用 table 要多几倍的渲染时间;当然使用 table 做表格是完全正确的。

    9.注释

    应该给一个模块文件写一个区块注释。

    示例:

    /**
    * @module mazey/api
    * @author Mazey <mazey@mazey.net>
    * @description test.
    * */
    

    相关文章

      网友评论

        本文标题:基于 Vue 的前端开发规范

        本文链接:https://www.haomeiwen.com/subject/oiohuftx.html