学会VUE的这些编码规范,让你的代码质量提升一个等级

邓占勇 2020-06-01 08:45:19
原文地址:https://segmentfault.com/a/1190000022392085

> 我的网站:<a>www.dzyong.top</a>
> 公众号: 【前端筱园】
> 作者:邓占勇

编码规范看看起来和实现项目功能并没有太大的联系,但是为什么它还是显得如此的重要呢。它主要有三大要素:可读性,可维护性,可变更性。

一个团队统一了编码规范,可以大大的提高开发效率与交互效率,可以很容易的看懂他人写的代码,使后期的维护也变得更加简单。今天来讲讲VUE只的编码规范。分为三个等级:必要的、强烈推荐、谨慎使用

一、必要的

1. 组件名为多个单词,而不是一个单词

反例


Vue.component('todo', {
  // ...
})
export default {
  name: 'Todo',
  // ...
}

正例

Vue.component('todo-item', {
  // ...
})
export default {
  name: 'TodoItem',
  // ...
}

2. 组件的data必须是一个函数

反例

export default {
  data: {
    name: 'dzy'
  }
}

正例

export default {
  data() {
    return {
      name: 'dzy'    
    }
  }
}

3. prop的定义应该尽量详细,至少需要指定类型

反例

props: ['status']

正例

props:{
  name: {
    type: String,
    default: 'dzy',
    required: true    
  }
}

4. 为v-for设置键值,总是用key配合v-for

反例

&lt;ul&gt;
  &lt;li v-for=&quot;todo in todos&quot;&gt;
    {{ todo.text }}
  &lt;/li&gt;
&lt;/ul&gt;

正例

&lt;ul&gt;
  &lt;li
    v-for=&quot;todo in todos&quot;
    :key=&quot;todo.id&quot;
  &gt;
    {{ todo.text }}
  &lt;/li&gt;
&lt;/ul&gt;

5. 永远不要把v-if与v-for用在同一个元素上

反例

&lt;ul&gt;
  &lt;li
    v-for=&quot;user in users&quot;
    v-if=&quot;shouldShowUsers&quot;
    :key=&quot;user.id&quot;
  &gt;
    {{ user.name }}
  &lt;/li&gt;
&lt;/ul&gt;

正例

&lt;ul v-if=&quot;shouldShowUsers&quot;&gt;
  &lt;li
    v-for=&quot;user in users&quot;
    :key=&quot;user.id&quot;
  &gt;
    {{ user.name }}
  &lt;/li&gt;
&lt;/ul&gt;

6. 为组件样式设置作用域

反例

&lt;style&gt;
.btn-close {
  background-color: red;
}
&lt;/style&gt;
正例

&lt;style scoped&gt;
.button {
  border: none;
  border-radius: 2px;
} 
&lt;/style&gt;

7. 私有属性名

Vue 使用 _ 前缀来定义其自身的私有属性,所以使用相同的前缀 (比如 _update) 有覆写实例属性的风险。即便你检查确认 Vue 当前版本没有用到这个属性名,也不能保证和将来的版本没有冲突。

对于 $ 前缀来说,其在 Vue 生态系统中的目的是暴露给用户的一个特殊的实例属性,所以把它用于私有属性并不合适。

不过,我们推荐把这两个前缀结合为 $_,作为一个用户定义的私有属性的约定,以确保不会和 Vue 自身相冲突。

正例

var myGreatMixin = {
  // ...
  methods: {
    update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    _update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    $update: function () {
      // ...
    }
  }
}

正例

var myGreatMixin = {
  // ...
  methods: {
    $_myGreatMixin_update: function () {
      // ...
    }
  }
}
// 甚至更好!
var myGreatMixin = {
  // ...
  methods: {
    publicMethod() {
      // ...
      myPrivateFunction()
    }
  }
}
​
function myPrivateFunction() {
  // ...
}
​
export default myGreatMixin

二、强烈推荐

1. 把每个组件独立成一个文件

反例

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

正例

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

2. 单文件的组件名一定是大写开头或者以“-”连接

反例

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

正例

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

3. 特定样式或基础组件,应该以同一个公共前缀开头

反例

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

正例

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

4. 如果一个组件是一个定制组件,即它不是一个公共组件,这种组件名应以The开头,表示唯一性,它不应该接收任何prop,如果接收prop那么说明它是一个公共组件

反例

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

正例

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

5.和父组件紧密耦合子组件,应以父组件名作为前缀名

反例

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

正例

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

6. 组件名应以高级别的单词开头,以描述性的修饰词结尾

反例

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

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

反例

&lt;!-- 在单文件组件、字符串模板和 JSX 中 --&gt;
&lt;MyComponent&gt;&lt;/MyComponent&gt;
&lt;!-- 在 DOM 模板中 --&gt;
&lt;my-component/&gt;

正例

&lt;!-- 在单文件组件、字符串模板和 JSX 中 --&gt;
&lt;MyComponent/&gt;
&lt;!-- 在 DOM 模板中 --&gt;
&lt;my-component&gt;&lt;/my-component&gt;

8. JS/JSX中的组件名应为驼峰命名

反例

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

正例

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

9. 组件名应为完整的英文单词,而不是缩写

反例

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

正例

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

**v10. 在声明prop的时候,名称应为驼峰命名,而在模板和JSX应用中应该是kebab-case**

反例

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

正例

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


**11. 多个attribute的元素应该分多行撰写,每个attribute一行**

反例

<img alt="Vue Logo">
<MyComponent foo="a" bar="b" baz="c"/>
正例

<img

alt="Vue Logo"

> <MyComponent
> foo="a"
> bar="b"
> baz="c"
> />


**12. 组件模板应该只包含简单的表达式,复杂的表达式应该重构为计算属性或方法**

反例

{{
fullName.split(' ').map(function (word) {

return word[0].toUpperCase() + word.slice(1)

}).join(' ')
}}

正例

\<!-- 在模板中 -->
{{ normalizedFullName }}
// 复杂表达式已经移入一个计算属性
computed: {
normalizedFullName: function () {

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

}
}
​```

13. 应该把复杂的计算属性,分割为极可能多的计算属性
反例

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

正例

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

14. 非空的attitude值应该始终带引号

反例

&lt;input type=text&gt;
&lt;AppSidebar :style={width:sidebarWidth+'px'}&gt;
正例

&lt;input type=&quot;text&quot;&gt;
&lt;AppSidebar :style=&quot;{ width: sidebarWidth + 'px' }&quot;&gt;

15. 指令可以缩写的建议缩写

&lt;input
  v-bind:value=&quot;newTodoText&quot;
  :placeholder=&quot;newTodoInstructions&quot;
&gt;
&lt;input
  v-on:input=&quot;onInput&quot;
  @focus=&quot;onFocus&quot;
&gt;
&lt;template v-slot:header&gt;
  &lt;h1&gt;Here might be a page title&lt;/h1&gt;
&lt;/template&gt;
​
&lt;template #footer&gt;
  &lt;p&gt;Here's some contact info&lt;/p&gt;
&lt;/template&gt;

欢迎访问我的网站:<a>www.dzyong.top</a>,关注我的公众号【前端筱园】,不错过我的每一篇推送

三、谨慎使用

1. 同一组的v-if和v-else最好使用key标识

什么意思呢,我们咋使用v-if和v-else时,都是成组出现的,当我们在一个上下文中,多次使用到v-if和v-else,这很容易引起混乱,很难看出那个v-else是属于那个v-else的。添加key标识还可以提高更新DOM的效率

&lt;div
  v-if=&quot;error&quot;
  key=&quot;search-status&quot;
&gt;
  错误:{{ error }}
&lt;/div&gt;
&lt;div
  v-else
  key=&quot;search-results&quot;
&gt;
  {{ results }}
&lt;/div&gt;

2. 元素选择器应该避免在scoped 中出现

在scoped样式中,类选择器比元素选择器很好,大量使用元素选择器是很慢的。

这是因为VUE在为了给样式设置作用域,vue会为元素添加一个唯一的attribute,如下图所示。然后修改选择器,使得元素选择器的元素中,只有带这个attribute的元素才会生效,所以大量使用元素+attribute组合的选择器,比类+attribute组合的选择器所涉及的元素更多,也就导致更慢。

3. 应该优先使用prop进行父子组件间的通信,而不是使用this$parent或改变prop

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

![gzh-code1.7a76f156.jpg](https://segmentfault.com/img/bVbF7mC "gzh-code1.7a76f156.jpg")

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。