vue 编码规范

为列表渲染设置属性key

切忌使用下标作为key,会失去虚拟Dom对比的优化

// v-for:key

// bad
// good

在v-if/v-if-else/v-else 中使用key

添加key,对比虚拟Dom时会认为是不同的节点,将旧元素直接移除并在相同位置添加新元素

// bad
{{error}}
{{results}}
// good
{{error}}
{{results}}

路由切换组件不变

路由的params参数改变不会重新触发组件的生命周期

解决方法

路由导航守卫 beforeRouteUpdate 拉取数据重新渲染视图,vue-router2.2+ 支持,推荐使用,观察 $route对象的变化,添加 watch,增加依赖追踪的内存开销


// bad
const user = {
  template:' ',
  watch:{
    '$route'(to,from){
      //...
    }
  }
}

// good
const user = {
  template:' ',
  watch: {
    '$route.query.id'(to,from){
      //...
    },
    '$route.query.page'(to,from){
      //...
    }
  }
}

为router-view组件添加属性key,利用虚拟dom渲染通过key对比节点的原理,不足之处在于切换路由组件会被销毁并重新创建


为所有路由统一添加 query

上级路由携带的 query 参数,需要在所有路由中携带,且不影响切换

解决方案

  • 使用全局守卫 beforeEach

// 缺点 全局守卫 beforeEach 会执行两次,且每次切换路由都会切换两次
const query = {refer: 'test'}
router.beforeEach((to,from,next)=>{
 to.query.referer ? next() : next({...to,query,...query})
})

  • 使用函数劫持(推荐使用)

const query = {refer: 'test'};
const transitionTo = router.history.transitionTo
 
router.history.transitionTo = function(location,onComplete,onAbout){
 location = typeof location === 'object' ? {...location,query:{...location.query,...query}} : {path:location,query}
 transitionTo.call(router.history,location,onComplete,onAbout)
}


区分 vuex 和 props 的使用边界

业务组件使用vuex维护状态,方便组件之间通信

通用组件使用 props 以及事件 进行父子组件通信,与业务解耦,在通用组件中定义props 尽可能详细,指定类型

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

推荐的做法

为过滤列表中的项目,可将循环列表替换为一个计算属性,返回过滤后的列表
为避免渲染本该隐藏的列表,可将v-if放到容器组件上

为组件样式设置作用域

通过scoped特性或者css Modules设置样式作用域,组件库使用class策略,使用容易理解的class名称且没有太高的选择器优先级,不容易导致冲突


// good

 
// good


避免在scoped中使用元素选择器

在scpoed样式中,类选择器优于元素选择器,大量使用元素选择器很慢

// bad

 
//good


避免隐性的父子组件通信

通过props和事件进行父子组件之间通信,不可使用this.$parent或改变prop

单文件组件命名

单文件组件名,单词首字母大写,或者始终是横线连接


// bad
components
|-mycomponent.vue
components
|-myComponent.vue
 
//good
components
|-MyComponent.vue
components
|-my-component.vue

基础组件名,以特定的前缀开头,组件不含Vuex store的全局状态

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

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

单例组件名,以The前缀命名,表示唯一性,该组件不接受任何prop,非复用组件

// bad
components
|-Heading.vue
|-MySiderbar.vue

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

精密耦合的组件名,与父组件紧密耦合的组件应该以父组件为前缀命名

// bad
components
|-TodoList.vue
|-TodoItem.vue
|-TodoButton.vue
components
|-SearchSidebar.vue
|-NavigationForSearchSideBar.vue
 
//good
components
|-TodoList/
 |-Item/
  |-index.vue
  |-Button.vue
 |-index.vue

//better
components
|-TodoList.vue
|-TodoListItem.vue
|-TodoListItemButton.vue
components
|-SearchSidebar.vue
|-SearchSideBarNavigation.vue



组件名中的单词顺序 高级别单词开头+描述性修饰词结尾

//bad
components
|-ClearSearchButton.vue
|-RunSearchButton.vue
|-SearchInput.vue
|-TermsCheckbox.vue
 
// good
components
|-SearchButtonClear.vue
|-SearchButtonRun.vue
|-SearchInputQuery.vue
|-SettingsCheckboxTerms.vue

完整单词的组件名

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


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

模板中的组件名大小写 组件名除根组件App外应始终由多个单词组成

//bad
vue.component('todo',{
 // ...
})
export default{
 name:'Todo',
 // ...
}
 
// good
vue.component('todo-item',{
 // ...

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

}

模板中的组件名大小写 本身html对大小写不敏感,尽量使用横线连接


// bad






 
// good





JS/JSX中的组件名大小写

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

自闭合组件

// bad




 
// good





prop名的大小写

// bad
props:{
 'greeting-text':String
}

 
//good
props:{
 greetingText:String
}


多个特性的元素

多行分隔对象的多个属性

// bad
< img src='https://vuejs.org' alt='vue logo'>

 
//good


模板中简单的表达式

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

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

简单的计算属性

复杂的计算属性应尽可能分为更多简单的属性,易于测试,易于阅读,低耦合

// bad
computed:{
 price:()=>{
  let basePrice = this.manufactureCost / (1 - this.profitMargin)
  return (
   basePrice -
   basePrice * (this.discountPrecent || 0)
  )
 }
}
 
// good
computed:{
 basePrice:()=>{
  return this.manufactureCost / (1 - this.profitMargin)
 }
 discount:()=>{
  return this.basePrice * (this.discountPrecent || 0)
 }
 finalPrice()=>{
  return this.basePrice - this.discount
 }
}

指令缩写

指令缩写保持统一,用 :标识 v-bind,@表示 v-on

你可能感兴趣的:(vue 编码规范)