• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 优先级 B 的规则:强烈推荐 (增强代码可读性)

    已发现这些规则可以提高大多数项目的可读性和/或开发人员体验。如果您违反它们,您的代码仍然会运行,但违反应该是罕见的且有充分理由的。

    组件文件

    每当构建系统可用于连接文件时,每个组件都应位于其自己的文件中。这有助于您在需要编辑组件或查看如何使用它时更快地找到它。

    反面例子

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

    正面例子

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


    单文件组件文件的大小写

    单文件组件的文件名应该要么始终是单词大写开头(PascalCase),要么始终是横线连接(kebab-case)。

    单词大写开头对于代码编辑器的自动补全最为友好,因为这使得我们在 JS(X)和模板中引用组件的方式尽可能地一致。然而,混用大小写的文件命名方式,有时候会导致其在大小写不敏感的文件系统中出现问题,这也是横线连接命名同样完全可取的原因。

    反面例子

    components/
    |- mycomponent.vue
    
    components/
    |- myComponent.vue
    

    正面例子

    components/
    |- MyComponent.vue
    
    components/
    |- my-component.vue
    


    基础组件名称

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

    反面例子

    components/
    |- MyButton.vue
    |- VueTable.vue
    |- Icon.vue
    

    正面例子

    components/
    |- BaseButton.vue
    |- BaseTable.vue
    |- BaseIcon.vue
    
    components/
    |- AppButton.vue
    |- AppTable.vue
    |- AppIcon.vue
    
    components/
    |- VButton.vue
    |- VTable.vue
    |- VIcon.vue
    


    单实例组件名称

    应该只有一个活动实例的组件应该以The前缀开头,表示只能有一个。

    这并不意味着该组件仅在单个页面中使用,而是每页仅使用一次。这些组件从不接受任何props,因为它们特定于您的应用程序,而不是它们在您的应用程序中的上下文。如果您发现需要添加props,这很好地表明这实际上是一个可重用的组件,目前每页仅使用一次。

    反面例子

    components/
    |- Heading.vue
    |- MySidebar.vue
    

    正面例子

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


    紧密耦合的组件名称

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

    反面例子

    components/
    |- TodoList.vue
    |- TodoItem.vue
    |- TodoButton.vue
    
    components/
    |- SearchSidebar.vue
    |- NavigationForSearchSidebar.vue
    

    正面例子

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


    组件名称中的单词顺序

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

    反面例子

    components/
    |- ClearSearchButton.vue
    |- ExcludeFromSearchInput.vue
    |- LaunchOnStartupCheckbox.vue
    |- RunSearchButton.vue
    |- SearchInput.vue
    |- TermsCheckbox.vue
    

    正面例子

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


    自闭合组件

    在单文件组件、字符串模板和 JSX 中,没有内容的组件应该是自闭合的——但在 DOM 模板里永远不要这样做。

    自闭合组件表示它们不仅没有内容,而且是刻意没有内容。其不同之处就好比书中的一页白纸,与贴有“本页有意留白”标签的白纸。而且没有了额外的闭合标签,你的代码也将更简洁。

    不幸的是,HTML 并不支持自闭合的自定义元素——官方的“空”元素除外。所以上述策略仅适用于在进入 DOM 之前,Vue 的模板编译器能够触达的地方,然后再产出符合 DOM 规范的 HTML。

    反面例子

    <!-- 在单文件组件、字符串模板和 JSX 中 -->
    <MyComponent></MyComponent>
    <!-- 在 DOM 模板中 -->
    <my-component/>
    

    正面例子

    <!-- 在单文件组件、字符串模板和 JSX 中 -->
    <MyComponent/>
    <!-- 在 DOM 模板中 -->
    <my-component></my-component>
    


    JS/JSX 中使用的组件名称

    JS/JSX 中的组件名应该始终是 PascalCase 的,尽管在较为简单的应用中,只使用 app.component 进行全局组件注册时,可以使用 kebab-case 字符串。

    反面例子

    app.component('myComponent', {
      // ...
    })
    import myComponent from './MyComponent.vue'
    export default {
      name: 'myComponent',
      // ...
    }
    export default {
      name: 'my-component',
      // ...
    }
    

    正面例子

    app.component('MyComponent', {
      // ...
    })
    app.component('my-component', {
      // ...
    })
    
    import MyComponent from './MyComponent.vue'
    export default {
      name: 'MyComponent',
      // ...
    }
    


    完整单词的组件名称

    组件名称应该倾向于完整的单词,而不是缩写。编辑器中的自动补全已经让书写长命名的代价非常之低了,而其带来的明确性却是非常宝贵的。不常用的缩写尤其应该避免。

    反面例子

    components/
    |- SdSettings.vue
    |- UProfOpts.vue
    

    正面例子

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


    Prop 命名

    在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板和 JSX 中应该始终使用 kebab-case。我们只是单纯地遵循了每种语言的约定。在 JavaScript 中 camelCase 更为自然。而在 HTML 中则是 kebab-case。

    反面例子

    props: {
      'greeting-text': String
    }
    <WelcomeMessage greetingText="hi"/>
    

    正面例子

    props: {
      greetingText: String
    }
    <WelcomeMessage greeting-text="hi"/>
    


    多个 attribute 的元素

    多个 attribute 的元素应该分多行撰写,每个 attribute 一行。在 JavaScript 中,用多行分隔对象的多个 property 是很常见的最佳实践,因为这样更易读。模板和 JSX 都需要做同样的考量。

    反面例子

    <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"
    />
    


    模板中的简单表达式

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

    反面例子

    {{
      fullName.split(' ').map((word) => {
        return word[0].toUpperCase() + word.slice(1)
      }).join(' ')
    }}
    

    正面例子

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


    简单的计算属性

    应该把复杂计算属性尽可能多地分割为更简单的计算属性。

    反面例子

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

    正面例子

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


    带引号的 attribute 值

    非空 HTML attribute 的值应该始终带有引号(单引号或双引号,选择未在 JS 里面使用的那个)。虽然在 HTML 中不带空格的 attribute 的值是可以不加引号的,但这样做往往导致大家避开空格,从而使得 attribute 的可读性变差。

    反面例子

    <input type=text>
    <AppSidebar :style={width:sidebarWidth+'px'}>
    

    正面例子

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


    指令缩写

    指令缩写(用:表示v-bind:@表示v-on:和用#表示v-slot)应该要么始终使用,要么始终不使用。

    反面例子

    <input
      v-bind:value="newTodoText"
      :placeholder="newTodoInstructions"
    >
    
    <input
      v-on:input="onInput"
      @focus="onFocus"
    >
    
    <template v-slot:header>
      <h1>Here might be a page title</h1>
    </template>
    
    <template #footer>
      <p>Here's some contact info</p>
    </template>
    

    正面例子

    <input
      :value="newTodoText"
      :placeholder="newTodoInstructions"
    >
    
    <input
      v-bind:value="newTodoText"
      v-bind:placeholder="newTodoInstructions"
    >
    
    <input
      @input="onInput"
      @focus="onFocus"
    >
    
    <input
      v-on:input="onInput"
      v-on:focus="onFocus"
    >
    
    <template v-slot:header>
      <h1>Here might be a page title</h1>
    </template>
    
    <template v-slot:footer>
      <p>Here's some contact info</p>
    </template>
    
    <template #header>
      <h1>Here might be a page title</h1>
    </template>
    
    <template #footer>
      <p>Here's some contact info</p>
    </template>