美文网首页
VUE项目规范

VUE项目规范

作者: 瘾_95f1 | 来源:发表于2019-05-07 14:48 被阅读0次

    一简介

    • 此规范基于脚手架vue-cli3.+
    • 从编写IDE,到项目结构,命名规范,代码风格,包括代码逻辑等,都做了说明

    二更新日志

    1.00.20190423

    • 修订人:瘾
    • 编写vue项目的开发规范1.00.20190423版本(初步版本)
    • 版本号规则:1 大版本记录, .00 小版本记录, .20190423 更新时间

    三项目结构

    3.1目录结构

    ├── node_modules  // 依赖包                      
    ├── public  // 静态资源目录不会被webpack编译         
    ├── src                        
    │   ├── assets  // 存放公共图片,css,js
    │   ├────└── images
    │   ├────└── style
    │   ├────└── js
    │   ├── components  // 非路由组件目录
    │   ├────└── common   // 非路由组件的全局公共组件
    │   ├── router  // 路由目录
    │   ├────└── index.js   // 路由入口,只负责入口,路由钩子,不负责具体的路由代码
    │   ├────└── route  // 路由文件夹,其下分模块,对路由进行管理
    │   ├── service   // 请求数据层文件
    │   ├────└── api  // 接口定义层文件,分模块去定义
    │   ├────└── request.js   // (axios)请求封装层,包括请求拦截
    │   ├────└── env.js   // 全局公共url的配置文件
    │   ├── store  // vuex
    │   ├────└── modules  // 开启命名空间,分模块处理
    │   ├────└── index.js   // vuex入口文件
    │   ├── views   // 路由组件,分模块,其模块与非路由组件中一一对应
    │   ├── directive   // 全局自定义指令层
    │   ├── filtres   // 全局自定义过滤层
    │   ├── App.vue   // 项目路由入口
    │   ├── main.js   // 入口文件  
    │   ├── .env.development   // 开发环境变量   
    │   ├── .env.production   // 生产环境变量
    │   ├── .env.test  // 测试环境变量
    │   ├── .eslintrc.js  // eslint配置
    │   ├── .gitignore  // git忽略文件
    │   ├── package.json  // 安装文件
    │   ├── babel.config.js   // babel配置
    │   ├── postcss.config.js  // css-loader配置
    │   ├── readme.md   // 项目介绍
    │   ├── vue.config.js   // 额外webpack配置
    

    3.2运行编译命令

    "scripts": {
        "serve": "vue-cli-service serve --mode development",
        "build": "vue-cli-service build --mode production",
        "build:test": "vue-cli-service build --mode test",
        "lint": "vue-cli-service lint"
    },
    
    环境变量配置

    .env.development

    NODE_ENV=development
    VUE_APP_ENV=development
    

    .env.production

    NODE_ENV=production
    VUE_APP_ENV=production
    

    .env.test

    NODE_ENV=production
    VUE_APP_ENV=test
    

    四代码风格

    4.1代码缩进

    四个空格缩进

    4.2代码顺序及要求

    <template>
      <ul>
        <li @click=""></li>
        <li :style=""></li>
        <li>{{ data }}</li>
      </ul>
    </template>
    <script>
      export default{
        name: 'TodoItem',
        data() {
          return {
            // 定义的每个data 属性必须有注释,注释规则: // 
          }
        },
        props: {
          id: {
              default: '',
              type: String
          }
        },
        components: {},
        beforeRouteEnter() {},
        beforeRouteUpdate() {},
        beforeRouteLeave() {},
        beforeCreate() {},
        created() {},
        beforeMount() {},
        mounted() {},
        beforeUpdate() {},
        updated() {},
        beforeDestroy() {},
        destroyed() {},
        watch: {},
        computed: {},
        directives: {},
        filter: {},
        methods: {
          //方法调用不需要注释,方法定义需要注释
          // 方法注释规则 /** */
        }
      }
    </script>
    <style lang="scss" scoped></style>
    

    五命名规范

    5.1文件夹命名

    文件夹命名采用小驼峰命名

    5.2组件命名

    组件名为多个单词

    组件名应该始终是多个单词的,且大驼峰命名,根组件 App 除外。

    正例:

    export default {
      name: 'TodoItem',
      // ...
    }
    

    反例:

    export default {
      name: 'Todo',
      // ...
    }
    
    单文件组件文件的大小写

    单文件组件的文件名应该要始终是单词大写开头 (PascalCase)

    正例:

    components/
    |- MyComponent.vue
    

    反例:

    components/
    |- myComponent.vue
    |- mycomponent.vue
    
    基础组件名

    应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 Base、App 或 V。

    正例:

    components/
    |- BaseButton.vue
    |- BaseTable.vue
    |- BaseIcon.vue
    

    反例:

    components/
    |- MyButton.vue
    |- VueTable.vue
    |- Icon.vue
    
    单例组件名

    只应该拥有单个活跃实例的组件应该以 The 前缀命名,以示其唯一性。
    这不意味着组件只可用于一个单页面,而是每个页面只使用一次。这些组件永远不接受任何 prop,因为它们是为你的应用定制的,而不是它们在你的应用中的上下文。如果你发现有必要添加 prop,那就表明这实际上是一个可复用的组件,只是目前在每个页面里只使用一次。

    正例:

    components/
    |- TheHeading.vue
    |- TheSidebar.vue
    

    反例:

    components/
    |- Heading.vue
    |- MySidebar.vue
    
    紧密耦合的组件名

    和父组件紧密耦合的子组件应该以父组件名作为前缀命名。
    如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字上。因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。

    正例:

    components/
    |- TodoList.vue
    |- TodoListItem.vue
    |- TodoListItemButton.vue
    components/
    |- SearchSidebar.vue
    |- SearchSidebarNavigation.vue
    

    反例:

    components/
    |- SearchSidebar.vue
    |- NavigationForSearchSidebar.vue
    
    组件名中的单词顺序

    组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾。

    正例:

    components/
    |- SearchButtonClear.vue
    |- SearchButtonRun.vue
    |- SearchInputQuery.vue
    |- SearchInputExcludeGlob.vue
    |- SettingsCheckboxTerms.vue
    |- SettingsCheckboxLaunchOnStartup.vue
    

    反例:

    components/
    |- ClearSearchButton.vue
    |- ExcludeFromSearchInput.vue
    |- LaunchOnStartupCheckbox.vue
    |- RunSearchButton.vue
    |- SearchInput.vue
    |- TermsCheckbox.vue
    
    模板中的组件名大小写

    总是 PascalCase 的

    正例:

    <!-- 在单文件组件和字符串模板中 -->
    <MyComponent/>
    

    反例:

    <!-- 在单文件组件和字符串模板中 -->
    <mycomponent/>
    <!-- 在单文件组件和字符串模板中 -->
    <myComponent/>
    
    完整单词的组件名

    组件名应该倾向于完整单词而不是缩写。

    正例:

    components/
    |- StudentDashboardSettings.vue
    |- UserProfileOptions.vue
    

    反例:

    components/
    |- SdSettings.vue
    |- UProfOpts.vue
    
    组件文件

    只要有能够拼接文件的构建系统,就把每个组件单独分成文件。
    当你需要编辑一个组件或查阅一个组件的用法时,可以更快速的找到它。

    正例:

    components/
    |- TodoList.vue
    |- TodoItem.vue
    

    反例:

    Vue.component('TodoList', {
      // ...
    })
    Vue.component('TodoItem', {
      // ...
    })
    

    5.3路由命名

    path使用全小写,多个单词用 - 分开,name与path保持一致
    先写name,再写path,component,meta

    正例:

    {
      name: "home-detail",
      path: "/home-detail",
      component: () => import("@/views/HomeDetail"),
      meta: {}
    }
    

    反例:

    {
      name: "homeDetail",
      path: "/HomeDetail",
      component: () => import("@/views/HomeDetail"),
      meta: {}
    }
    

    5.4请求命名

    所有定义的接口以api开头小驼峰命名,尽量语义化,不要简写

    正例:

    export const apiHomeList = (pageInfo)=>ajax('/web/app/list.do',{pageInfo})
    

    反例:

    export const homeList = (pageInfo)=>ajax('/web/app/list.do',{pageInfo})
    

    5.5class命名

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

    正例:

    .test-header{
        font-size: 20px;
    }
    

    反例:

    .testheader{
        font-size: 20px;
    }
    

    5.6其他命名

    以上规则没有提到的统一采用小驼峰命名,语义化,不简写

    六代码逻辑

    6.1props定义

    props 定义应该尽量详细。
    在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。

    正例:

    props: {
      status: String
    }
    // 更好的做法!
    props: {
      status: {
        type: String,
        required: true,
        validator: function (value) {
          return [
            'syncing',
            'synced',
            'version-conflict',
            'error'
          ].indexOf(value) !== -1
        }
      }
    }
    

    反例:

    props: ['status']
    

    6.2循环和判断

    为v-for设置键值

    总是用 key 配合 v-for。
    在组件上总是必须用 key 配合 v-for,以便维护内部组件及其子树的状态。甚至在元素上维护可预测的行为,比如动画中的对象固化 (object constancy),也是一种好的做法。

    正例:

    <ul>
      <li
        v-for="todo in todos"
        :key="todo.id"
      >
        {{ todo.text }}
      </li>
    </ul>
    

    反例:

    <ul>
      <li v-for="todo in todos">
        {{ todo.text }}
      </li>
    </ul>
    
    循环

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

    避免 v-if 和 v-for 用在一起

    永远不要把 v-if 和 v-for 同时用在同一个元素上。
    一般我们在两种常见的情况下会倾向于这样做:
    为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。
    为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。这种情形下,请将 v-if 移动至容器元素上 (比如 ul, ol)。

    正例:

    <ul v-if="shouldShowUsers">
      <li
        v-for="user in users"
        :key="user.id"
      >
        {{ user.name }}
      </li>
    </ul>
    

    反例:

    <ul>
      <li
        v-for="user in users"
        v-if="shouldShowUsers"
        :key="user.id"
      >
        {{ user.name }}
      </li>
    </ul>
    
    在 v-if/v-if-else/v-else 中使用 key

    如果一组 v-if + v-else 的元素类型相同,最好使用 key (比如两个 <div> 元素)。

    正例:

    <div
      v-if="error"
      key="search-status"
    >
      错误:{{ error }}
    </div>
    <div
      v-else
      key="search-results"
    >
      {{ results }}
    </div>
    

    反例:

    <div v-if="error">
      错误:{{ error }}
    </div>
    <div v-else>
      {{ results }}
    </div>
    

    6.3多个特性的元素

    多个特性的元素应该分多行撰写,每个特性一行。

    正例:

    <img
      src="https://vuejs.org/images/logo.png"
      alt="Vue Logo"
    >
    <MyComponent
      foo="a"
      bar="b"
      baz="c"
    />
    

    反例:

    <img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
    <MyComponent foo="a" bar="b" baz="c"/>
    

    6.4computed

    模板中简单的表达式

    组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。
    复杂表达式会让你的模板变得不那么声明式。我们应该尽量描述应该出现的是什么,而非如何计算那个值。而且计算属性和方法使得代码可以重用。

    正例:

    <!-- 在模板中 -->
    {{ normalizedFullName }}
    // 复杂表达式已经移入一个计算属性
    computed: {
      normalizedFullName: function () {
        return this.fullName.split(' ').map(function (word) {
          return word[0].toUpperCase() + word.slice(1)
        }).join(' ')
      }
    }
    

    反例:

    {{
      fullName.split(' ').map(function (word) {
        return word[0].toUpperCase() + word.slice(1)
      }).join(' ')
    }}
    
    简单的计算属性

    正例:

    computed: {
      basePrice: function () {
        return this.manufactureCost / (1 - this.profitMargin)
      },
      discount: function () {
        return this.basePrice * (this.discountPercent || 0)
      },
      finalPrice: function () {
        return this.basePrice - this.discount
      }
    }
    

    反例:

    computed: {
      price: function () {
        var basePrice = this.manufactureCost / (1 - this.profitMargin)
        return (
          basePrice -
          basePrice * (this.discountPercent || 0)
        )
      }
    }
    

    6.5引号

    带引号的特性值

    非空 HTML 特性值应该始终带引号 (单引号或双引号,优先使用 "" , JS 优先使用 '' )。
    在 HTML 中不带空格的特性值是可以没有引号的,但这样做常常导致带空格的特征值被回避,导致其可读性变差。

    正例:

    <AppSidebar :style="{ width: sidebarWidth + 'px' }">
    

    反例:

    <AppSidebar :style={width:sidebarWidth+'px'}>
    
    在js中

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

    正例:

    const foo = '后除'
    const bar = `${foo},前端工程师`
    

    反例:

    const foo = "后除"
    const bar = foo + ",前端工程师"
    

    6.6指令缩写

    都用指令缩写 (用 : 表示 v-bind: 和用 @ 表示 v-on:)

    正例:

    <input
      @input="onInput"
      @focus="onFocus"
    >
    

    反例:

    <input
      v-bind:value="newTodoText"
      :placeholder="newTodoInstructions"
    >
    

    6.7scoped

    元素选择器应该避免在 scoped 中出现。
    在 scoped 样式中,类选择器比元素选择器更好,因为大量使用元素选择器是很慢的。

    正例:

    <template>
      <button class="btn btn-close">X</button>
    </template>
     
    <style scoped>
    .btn-close {
      background-color: red;
    }
    </style>
    

    反例:

    <template>
      <button>X</button>
    </template>
     
    <style scoped>
    button {
      background-color: red;
    }
    </style>
    

    6.8隐性的父子组件通信

    应该优先通过 prop 和事件进行父子组件之间的通信,而不是 this.$parent 或改变 prop。

    正例:

    Vue.component('TodoItem', {
      props: {
        todo: {
          type: Object,
          required: true
        }
      },
      template: `
        <input
          :value="todo.text"
          @input="$emit('input', $event.target.value)"
        >
      `
    })
    

    反例:

    Vue.component('TodoItem', {
      props: {
        todo: {
          type: Object,
          required: true
        }
      },
      methods: {
        removeTodo () {
          var vm = this
          vm.$parent.todos = vm.$parent.todos.filter(function (todo) {
            return todo.id !== vm.todo.id
          })
        }
      },
      template: `
        <span>
          {{ todo.text }}
          <button @click="removeTodo">
            X
          </button>
        </span>
      `
    })
    

    6.9全局状态管理

    应该优先通过 Vuex 管理全局状态,而不是通过 this.$root 或一个全局事件总线。

    正例:

    // store/modules/todos.js
    export default {
      state: {
        list: []
      },
      mutations: {
        REMOVE_TODO (state, todoId) {
          state.list = state.list.filter(todo => todo.id !== todoId)
        }
      },
      actions: {
        removeTodo ({ commit, state }, todo) {
          commit('REMOVE_TODO', todo.id)
        }
      }
    }
    <!-- TodoItem.vue -->
    <template>
      <span>
        {{ todo.text }}
        <button @click="removeTodo(todo)">
          X
        </button>
      </span>
    </template>
     
    <script>
    import { mapActions } from 'vuex'
     
    export default {
      props: {
        todo: {
          type: Object,
          required: true
        }
      },
      methods: mapActions(['removeTodo'])
    }
    </script>
    

    反例:

    // main.js
    new Vue({
      data: {
        todos: []
      },
      created: function () {
        this.$on('remove-todo', this.removeTodo)
      },
      methods: {
        removeTodo: function (todo) {
          var todoIdToRemove = todo.id
          this.todos = this.todos.filter(function (todo) {
            return todo.id !== todoIdToRemove
          })
        }
      }
    })
    

    6.10关于es6

    6.10.1块级作用域

    (1)let 取代 var

    S6 提出了两个新的声明变量的命令:let和const。其中,let完全可以取代var,因为两者语义相同,而且let没有副作用,不存在变量提升。

    (2)全局常量和线程安全

    在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

    1. const优于let有几个原因。一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个是const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率,也就是说let和const的本质区别,其实是编译器内部的处理不同。
    2. const声明常量还有两个好处,一是阅读代码的人立刻会意识到不应该修改这个值,二是防止了无意间修改变量值所导致的错误。
    3. 所有的函数都应该设置为常量。
    4. 长远来看,JavaScript 可能会有多线程的实现(比如 Intel 公司的 River Trail 那一类的项目),这时let表示的变量,只应出现在单线程运行的代码中,不能是多线程共享的,这样有利于保证线程安全。

    6.10.2字符串

    静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。

    // bad
    const a = "foobar";
    const b = 'foo' + a + 'bar';
    
    // acceptable
    const c = `foobar`;
    
    // good
    const a = 'foobar';
    const b = `foo${a}bar`;
    

    6.10.3解构赋值

    使用数组成员对变量赋值时,优先使用解构赋值。

    const arr = [1, 2, 3, 4];
    
    // bad
    const first = arr[0];
    const second = arr[1];
    
    // good
    const [first, second] = arr;
    

    函数的参数如果是对象的成员,优先使用解构赋值。

    // bad
    function getFullName(user) {
      const firstName = user.firstName;
      const lastName = user.lastName;
    }
    
    // good
    function getFullName(obj) {
      const { firstName, lastName } = obj;
    }
    
    // best
    function getFullName({ firstName, lastName }) {
    }
    

    如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。这样便于以后添加返回值,以及更改返回值的顺序。

    // bad
    function processInput(input) {
      return [left, right, top, bottom];
    }
    
    // good
    function processInput(input) {
      return { left, right, top, bottom };
    }
    
    const { left, right } = processInput(input);
    

    6.10.4对象

    单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个成员以逗号结尾

    // bad
    const a = { k1: v1, k2: v2, };
    const b = {
      k1: v1,
      k2: v2
    };
    
    // good
    const a = { k1: v1, k2: v2 };
    const b = {
      k1: v1,
      k2: v2,
    };
    

    对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用Object.assign方法。

    // bad
    const a = {};
    a.x = 3;
    
    // if reshape unavoidable
    const a = {};
    Object.assign(a, { x: 3 });
    
    // good
    const a = { x: null };
    a.x = 3;
    

    如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义。

    // bad
    const obj = {
      id: 5,
      name: 'San Francisco',
    };
    obj[getKey('enabled')] = true;
    
    // good
    const obj = {
      id: 5,
      name: 'San Francisco',
      [getKey('enabled')]: true,
    };
    

    上面代码中,对象obj的最后一个属性名,需要计算得到。这时最好采用属性表达式,在新建obj的时候,将该属性与其他属性定义在一起。这样一来,所有属性就在一个地方定义了。

    另外,对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。

    var ref = 'some value';
    
    // bad
    const atom = {
      ref: ref,
    
      value: 1,
    
      addValue: function (value) {
        return atom.value + value;
      },
    };
    
    // good
    const atom = {
      ref,
    
      value: 1,
    
      addValue(value) {
        return atom.value + value;
      },
    };
    

    6.10.5数组

    使用扩展运算符(...)拷贝数组。

    // bad
    const len = items.length;
    const itemsCopy = [];
    let i;
    
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // good
    const itemsCopy = [...items];
    

    使用 Array.from 方法,将类似数组的对象转为数组。

    const foo = document.querySelectorAll('.foo');
    const nodes = Array.from(foo);chou
    

    6.10.6函数

    立即执行函数可以写成箭头函数的形式。

    (() => {
      console.log('Welcome to the Internet.');
    })();
    

    那些需要使用函数表达式的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了 this。

    // bad
    [1, 2, 3].map(function (x) {
      return x * x;
    });
    
    // good
    [1, 2, 3].map((x) => {
      return x * x;
    });
    
    // best
    [1, 2, 3].map(x => x * x);
    

    箭头函数取代Function.prototype.bind,不应再用 self/_this/that 绑定 this。

    // bad
    const self = this;
    const boundMethod = function(...params) {
      return method.apply(self, params);
    }
    
    // acceptable
    const boundMethod = method.bind(this);
    
    // best
    const boundMethod = (...params) => method.apply(this, params);
    

    简单的、单行的、不会复用的函数,建议采用箭头函数。如果函数体较为复杂,行数较多,还是应该采用传统的函数写法。
    所有配置项都应该集中在一个对象,放在最后一个参数,布尔值不可以直接作为参数。

    // bad
    function divide(a, b, option = false ) {
    }
    
    // good
    function divide(a, b, { option = false } = {}) {
    }
    

    不要在函数体内使用 arguments 变量,使用 rest 运算符(...)代替。因为 rest 运算符显式表明你想要获取参数,而且 arguments 是一个类似数组的对象,而 rest 运算符可以提供一个真正的数组

    // bad
    function concatenateAll() {
      const args = Array.prototype.slice.call(arguments);
      return args.join('');
    }
    
    // good
    function concatenateAll(...args) {
      return args.join('');
    }
    

    使用默认值语法设置函数参数的默认值。

    // bad
    function handleThings(opts) {
      opts = opts || {};
    }
    
    // good
    function handleThings(opts = {}) {
      // ...
    }
    

    6.10.7Map结构

    注意区分 Object 和 Map,只有模拟现实世界的实体对象时,才使用 Object。如果只是需要key: value的数据结构,使用 Map 结构。因为 Map 有内建的遍历机制。

    let map = new Map(arr);
    
    for (let key of map.keys()) {
      console.log(key);
    }
    
    for (let value of map.values()) {
      console.log(value);
    }
    
    for (let item of map.entries()) {
      console.log(item[0], item[1]);
    }
    

    6.10.8Class

    总是用 Class,取代需要 prototype 的操作。因为 Class 的写法更简洁,更易于理解。

    // bad
    function Queue(contents = []) {
      this._queue = [...contents];
    }
    Queue.prototype.pop = function() {
      const value = this._queue[0];
      this._queue.splice(0, 1);
      return value;
    }
    
    // good
    class Queue {
      constructor(contents = []) {
        this._queue = [...contents];
      }
      pop() {
        const value = this._queue[0];
        this._queue.splice(0, 1);
        return value;
      }
    }
    

    使用extends实现继承,因为这样更简单,不会有破坏instanceof运算的危险。

    // bad
    const inherits = require('inherits');
    function PeekableQueue(contents) {
      Queue.apply(this, contents);
    }
    inherits(PeekableQueue, Queue);
    PeekableQueue.prototype.peek = function() {
      return this._queue[0];
    }
    
    // good
    class PeekableQueue extends Queue {
      peek() {
        return this._queue[0];
      }
    }
    

    6.10.9模块

    首先,Module 语法是 JavaScript 模块的标准写法,坚持使用这种写法。使用import取代require

    // bad
    const moduleA = require('moduleA');
    const func1 = moduleA.func1;
    const func2 = moduleA.func2;
    
    // good
    import { func1, func2 } from 'moduleA';
    

    使用export取代module.exports。

    // commonJS的写法
    var React = require('react');
    
    var Breadcrumbs = React.createClass({
      render() {
        return <nav />;
      }
    });
    
    module.exports = Breadcrumbs;
    
    // ES6的写法
    import React from 'react';
    
    class Breadcrumbs extends React.Component {
      render() {
        return <nav />;
      }
    };
    
    export default Breadcrumbs;
    

    如果模块只有一个输出值,就使用export default,如果模块有多个输出值,就不使用export default,export default与普通的export不要同时使用。

    不要在模块输入中使用通配符。因为这样可以确保你的模块之中,有一个默认输出(export default)。

    // bad
    import * as myObject from './importModule';
    
    // good
    import myObject from './importModule';
    

    如果模块默认输出一个函数,函数名的首字母应该小写。

    function makeStyleGuide() {
    }
    
    export default makeStyleGuide;
    

    如果模块默认输出一个对象,对象名的首字母应该大写。

    const StyleGuide = {
      es6: {
      }
    };
    
    export default StyleGuide;
    

    七ESlint的使用

    ESLint 是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。

    首先,安装 ESLint。

    npm i -g eslint
    

    然后,安装 Airbnb 语法规则,以及 import、a11y、react 插件。

    npm i -g eslint-config-airbnb
    npm i -g eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react
    

    最后,在项目的根目录下新建一个.eslintrc文件,配置 ESLint。

    {
      "extends": "eslint-config-airbnb"
    }
    

    现在就可以检查,当前项目的代码是否符合预设的规则。

    index.js文件的代码如下。

    var unusued = 'I have no purpose!';
    
    function greet() {
        var message = 'Hello, World!';
        alert(message);
    }
    
    greet();
    

    使用 ESLint 检查这个文件,就会报出错误。

    $ eslint index.js
    index.js
      1:1  error  Unexpected var, use let or const instead          no-var
      1:5  error  unusued is defined but never used                 no-unused-vars
      4:5  error  Expected indentation of 2 characters but found 4  indent
      4:5  error  Unexpected var, use let or const instead          no-var
      5:5  error  Expected indentation of 2 characters but found 4  indent
    
    ✖ 5 problems (5 errors, 0 warnings)
    

    上面代码说明,原文件有五个错误,其中两个是不应该使用var命令,而要使用let或const;一个是定义了变量,却没有使用;另外两个是行首缩进为 4 个空格,而不是规定的 2 个空格。

    八注释

    JS
    属性注释:  //
    方法注释:  /**
                * @desc 解释
                * @param {数据类型} 参数名 参数解释
                */
    对象注释举例:  /**
                    * @desc 查询所有消息
                    * @param {Object} pageInfo     分页对象
                    * @property {int} pageNum      页号
                    * @property {int} pageSize     每页条数
                    */
    
    组件
    <!--公用组件:数据表格
     /**
      * @desc 组件名称
      * @module 组件存放位置
      * @desc 组件描述
      * @author 组件作者
      * @date 2018年8月13日17:22:43
      * @param {Object} [title]    - 参数说明
      * @param {String} [columns] - 参数说明
      * @example 调用示例
      *  <hbTable :title="title" :columns="columns" :tableData="tableData"></hbTable>
      */
    -->
    

    九vscode插件

    Auto Rename Tag   // 自动重命名配对的HTML / XML标签
    Chinese (Simplified) Language Pack for Visual Studio Code   // ide汉化
    Color Highlight   // css 颜色高亮
    CSS Peek    // 能够查看CSS ID和类的字符串作为HTML文件中相应的CSS定义
    CSScomb   // css 格式化
    Debugger for Chrome   // 让 vscode 映射 chrome 的 debug功能,用 vscode 来打断点调试
    language-stylus   // 支持.styl样式
    Live Server   // 项目服务端口5500 启动
    Markdown All in One   // 拓展md
    Markdown Preview Enhanced  // md 预览
    open in browser  // 浏览器打开html
    px2rem  // rem配置
    TODO Highlight  // TODO 高亮
    TSLint  // TS校验
    TypeScript Importer  // TS拓展
    Vetur // vue 格式化配置 高亮
    vscode-icons  // 文件图标
    Vue VSCode Snippets  // vue 代码提示
    

    相关文章

      网友评论

          本文标题:VUE项目规范

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