Vue front-end development specification (Shandong Shumanjianghu)

1. Compulsory

1. Component name with multiple words

Component names should always be multiple words, except the root component App.

Normal example:

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

Counterexample:

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

2. Component data

The component's data must be a function.
When using the data property in a component (anywhere except new Vue), its value must be a function that returns an object.

Normal example:

// In a .vue file
export default {
  data () {
    return {
      foo: 'bar' } } } // 在一个 Vue 的根实例上直接使用对象是可以的, // 因为只存在一个这样的实例。 new Vue({ data: { foo: 'bar' } }) 

Counterexample:

export default {
  data: {
    foo: 'bar' } } 

3. Prop Definition

Prop definitions should be as detailed as possible.
In the code you submit, the definition of prop should be as detailed as possible, at least specifying its type.

Normal example:

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

Counterexample:

// 这样做只有开发原型系统时可以接受
props: ['status']

4. Set the key value for v-for

Always use key with v-for.
A key must always be used with v-for on a component in order to maintain the state of the internal component and its subtrees. Even maintaining predictable behavior on elements, such as object constancy in animations, is a good practice.

Normal example:

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

Counterexample:

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

5. Avoid using v-if and v-for together

Never use both v-if and v-for on the same element.
Generally we tend to do this in two common situations:

  • To filter items in a list (eg v-for="user in users" v-if="user.isActive"). In this case, replace users with a computed property (such as activeUsers) that returns a filtered list.
  • To avoid rendering lists that should be hidden (eg v-for="user in users" v-if="shouldShowUsers"). In this case, move the v-if to the container element (eg ul, ol).

Normal example:

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

Counterexample:

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

6. Scope Component Styles

Styles in the top-level App and Layout components can be global to the application, but all other components should be scoped.
This rule is only relevant for single-file components. You don't have to use the scoped feature. Setting scope is also possible through CSS Modules, which is a class-based BEM-like strategy, but you can also use other libraries or conventions.

Regardless, for component libraries, we should prefer a class-based strategy over the scoped feature.
This makes it easier to override internal styles: use human-readable class names without too high selector precedence, and less likely to cause conflicts.

Normal example:

<template>
  <button class="c-Button c-Button--close">X</button>
</template>

<!-- 使用 BEM 约定 -->
<style>
.c-Button {
  border: none;
  border-radius: 2px;
}

.c-Button--close {
  background-color: red;
}
</style>

Counterexample:

<template>
  <button class="btn btn-close">X</button>
</template>

<style>
.btn-close {
  background-color: red;
}
</style>

<template>
  <button class="button button-close">X</button>
</template>

<!-- 使用 `scoped` 特性 -->
<style scoped>
.button {
  border: none;
  border-radius: 2px;
}

.button-close {
  background-color: red;
}
</style>

2. Strongly recommended (enhanced readability)

1. Component file

As long as there is a build system that can concatenate files, separate each component into files.
When you need to edit a component or check the usage of a component, you can find it faster.

Normal example:

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

Counterexample:

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

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

2. Case of single-file component files

Filenames for single-file components should either always start with a word capitalized (PascalCase)

Normal example:

components/
|- MyComponent.vue

Counterexample:

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

3. Basic component name

Base components that apply specific styles and conventions (that is, components that present classes, logicless, or stateless) should all start with a specific prefix, such as Base, App, or V.

Normal example:

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

Counterexample:

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

4. Singleton component name

Components that should only have a single active instance should be named with the prefix The prefix for uniqueness.
This does not mean that the component can only be used on a single page, but only once per page. These components never accept any props because they are customized for your app, not their context in your app. If you find it necessary to add props, it means that this is actually a reusable component that is currently only used once per page.

Normal example:

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

Counterexample:

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

5. Tightly coupled component names

Subcomponents that are tightly coupled to their parent should be named with the parent's name as a prefix.
If a component only makes sense in the context of a parent component, this relationship should be reflected in its name. Because editors usually organize files alphabetically, doing this keeps related files together.

Normal example:

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

Counterexample:

components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue

6. Word order in component names

Component names should start with a high-level (usually generalized) word and end with a descriptive modifier.

Normal example:

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

Counterexample:

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

7. Component name case in templates

Always PascalCase

Normal example:

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

Counterexample:

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

8. Full word component name

Component names should favor full words rather than abbreviations.

Normal example:

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

Counterexample:

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

9. Elements with Multiple Properties

Elements with multiple attributes should be written on multiple lines, one for each attribute.

Normal example:

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

Counterexample:

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

10. Simple expressions in templates

Component templates should only contain simple expressions, complex expressions should be refactored into computed properties or methods.
Complex expressions make your templates less declarative. Instead of how to calculate that value, we should try to describe what should appear. And computed properties and methods make code reusable.

Normal example:

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

Counterexample:

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

11. Simple Computed Properties

Normal example:

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

Counterexample:

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

12. Quoted attribute values

Non-empty HTML attribute values ​​should always be quoted (single or double, whichever is not used in your JS).
Attribute values ​​without spaces can be left unquoted in HTML, but doing so often results in character values ​​with spaces being avoided, making them less readable.

Normal example:

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

Counterexample:

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

13. Instruction Abbreviations

Both use instruction abbreviations (use : for v-bind: and @ for v-on: )

Normal example:

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

Counterexample:

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

3. Recommended

1. Order of top-level elements of a single-file component

Single-file components should always have the <script>, <template>, and <style> tags in the same order. And <style> should be at the end, because there must be at least one of the other two tags.

Normal example:

<!-- ComponentA.vue -->
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>

4. Use with caution (potentially dangerous mode)

1. Not using key in v-if/v-if-else/v-else

If a set of v-if + v-else elements are of the same type, it is better to use a key (such as two <div> elements).

Normal example:

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

Counterexample:

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

2. Element selectors in scoped

Element selectors should be avoided in scoped.
In the scoped style, class selectors are preferable to element selectors, because heavy use of element selectors is slow.

Normal example:

<template>
  <button class="btn btn-close">X</button>
</template>

<style scoped>
.btn-close {
  background-color: red;
}
</style>

Counterexample:

<template>
  <button>X</button>
</template>

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

3. Implicit parent-child component communication

Communication between parent and child components should be done via props and events in preference to this.$parent or changing props.

Normal example:

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

Counterexample:

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> ` }) 

4. Non-Flux Global State Management

Global state should be managed via Vuex in preference to this.$root or a global event bus.

Normal example:

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

Counterexample:

// 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 }) } } }) 

appendix

1. It is recommended to use vs code for front-end coding, and the Tab size is specified as 2 spaces

  1. vs code configuration
{
  "editor.tabSize": 2,
  "workbench.startupEditor": "newUntitledFile",
  "workbench.iconTheme": "vscode-icons", // 以下为stylus配置 "stylusSupremacy.insertColons": false, // 是否插入冒号 "stylusSupremacy.insertSemicolons": false, // 是否插入分好 "stylusSupremacy.insertBraces": false, // 是否插入大括号 "stylusSupremacy.insertNewLineAroundImports": false, // import之后是否换行 "stylusSupremacy.insertNewLineAroundBlocks": false, // 两个选择器中是否换行 "vetur.format.defaultFormatter.html": "js-beautify-html", "eslint.autoFixOnSave": true, "eslint.validate": [ "javascript", { "language": "html", "autoFix": true }, { "language": "vue", "autoFix": true }, "javascriptreact", "html", "vue" ], "eslint.options": { "plugins": ["html"] }, "prettier.singleQuote": true, "prettier.semi": false, "javascript.format.insertSpaceBeforeFunctionParenthesis": false, "vetur.format.js.InsertSpaceBeforeFunctionParenthesis": false, "vetur.format.defaultFormatter.js": "prettier", // "prettier.eslintIntegration": true } 
  1. vs code plugin
  • Auto Close Tag
  • Path Intellisense
  • Prettier
  • Winter
  • vscode-icons

Author: silianpan
Link: https://juejin.im/post/5ada9b586fb9a07aaf34c746
Source: Nuggets The
copyright belongs to the author. For commercial reprints, please contact the author for authorization, and for non-commercial reprints, please indicate the source.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324839067&siteId=291194637