随笔 - 2649  文章 - 2452  评论 - 0  阅读 - 80424

vue开发规范

前言

开发中,良好的项目风格规范,不仅能对项目起到优化的作用, 还能让我们更快的读懂项目。

#目录

(一) 组件
(二) prop属性
(三) 样式
(四) 关于key
(五) 模板
(六) 计算属性computed
(七) 指令
(八) 私有属性名
(九) 带引号的特性值
(十) 组件/实例
(十一) 元素特性的顺序
(十二) 非Flux的全局状态管理

#(一) 组件

#1.命名规范

一个良好的命名规范能够在绝大多数中改善可读性和开发体验

解决方案
  • 方案一 : 单文件组件的文件的大小写

    单文件组建的文件名始终是首字母大写 (PascalCase),或始终是横线链接 (kebab-case)

components
 => my-components.vue
 => MyComponents.vue
  • 方案二 : 基础组件名

    应用特定样式和约定的组件(展示类,无逻辑无状态的组件)应该全部以一个特定的前缀开头,比附 Base, App 或 V,优点如下:
    当以私募顺序排列时,应用的基础组件会全部列在一起,容易识别,因为是多个单词,可以避免包裹简单的组件时随意选择前缀(比如 Mybutton,VueButton)

components
=>BaseButton.vue
=>BaseIcon.vue
=>BaseSearch.vue
  • 方案三: 单例组件名

    只拥有单个活跃实例的组件以 The 前缀命名,以示其唯一性,但这并不是因为这组件只可只用于一个单页面,而是每个页面只用一次,这些组件永远不接受任何 prop ,因为他们是为你的应用定制的,而不是应用的上下文

components
=>TheHeading.vue
=>TheSidebar.vue
  • 方案四: 紧密耦合的组件名

    以父组件紧密耦合的子组件应该以父组件作为前缀命名

components
=>TodoList.vue
=>TodoListItem.vue
=>TodoLiisItemButton
  • 方案五: 组件名中的单词顺序

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

    >

compenents
=>SearchButtonClear.vue
=>SearchButtonRun.vue
=>SearchInputQuery.vue
  • 方案六 : 完整单词的组件名

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

components
=>UserProfileOptions.vue
  • 方案七 : 组件为多个单词

组件名应该始终有多个单词组成,根组件 App 除外.这样做可以避免与现有的以及未来的 HTML 冲突

Vue.component('todo-item',{
    
    })
  • 方案八: 模板中的组件名大小写

    单文件组件和字符串模板的组件名应该总是单词首字母大写
    但是在 DOM 模板中总是横线连接的

<template>
    <my-component></my-component>
    <MyComponent></MyComponent>
</template>
  • 方案九: 自闭合组件

    在单文件组件,字符串模板和 JSX 中没有内容的组件应该是自闭合的,但是在 DOM 模板中永远不要这样做。
    js/jsx中的组件名应该始终都是PascalCase的,尽管在较为简单的应用中只使用Vue.component进行全局组件注册时,可以使用kebab-case字符串。

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

#2.组件里的多个特性元素的撰写格式

多个特性元素应该分多行撰写,每个特性一行. 方便易读

<template>
    <MyComponent
        foo="1"
        bar="2"
        seo="3"> 
    </MyComponent>
</template>

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

当在组件中使用 data 属性的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。
当 data 的值是一个对象时,它会在这个组件的所有实例之间共享。想象一下,假如一个 TodoList 组件的数据是这样的:

<script>
export default{
    data: {
        listTitle: '',
        todos: []
    }
}
</script>

当我们重复使用这个组件的时候,就会产生问题。因为每个组件的实例都引用了相同的数据对象,更改其中一个列表的标题就会改变其它每一个列表的标题。
而这与我们预期的实现效果并不同。我们希望的是每个组件实例都管理自己的数据,因此:每个实例必须生成一个独立的数据对象。在data函数中返回这个对象即可。

<script>
export default{
    data: function(){
        reuturn {
            listTitle: '',
            todos: []
        }
    }
}
</script>
<script>
export default{
    data() {
        reuturn {
            listTitle: '',
            todos: []
        }
    }
}
</script>
//在一个vue的根实例上直接使用对象是可以的
//因为只存在一个这样的实例
new Vue({
    data: {
        listTitle: '',
        todos: []
    }
})

#(二) prop属性

#1.命名规范

在声明 prop 的时候,其命名应该始终使用驼峰式命名规则,而在 JSX 中应该使用使用横线连接的方式

<template>
    <MyComponent getting-text="haha"> </MyComponent>
</template>
<script>
export default {
    props:{
        gettingText:String
    }
}
</script>   

#2.定义应该尽量详细

在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。
细致的prop 定义有两个好处:
(1) 它们写明了组件的 API,所以很容易看懂组件的用法;
(2) 在开发环境下,如果向一个组件提供格式不正确的 prop,Vue 将会告警,以帮助你捕获潜在的错误来源。

<script>
export default {
    props: {
        status: {
            type: String,
            required: true,
            validator: function (value) {
            return [
                'syncing',
                'synced',
                'version-conflict',
                'error'
            ].indexOf(value) !== -1
            }
        }
    }
}
</script>

#(三) 样式

#1.为组件样式设置作用域

通过 scoped 特性来设置组件样式作用域

<template>
<style scpoed>
    /* 样式代码 只在当前组件内生效 */
</style>
</template>

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

大量的元素选择器比如(button[data-v-fsdfae4]) 会比类和特性组合的选择器慢

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

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

#(四) 关于key

#1.为列表渲染设置属性 key

key 这个特殊属性主要用在 Vue 的虚拟 DOM 算法中,在对比新旧虚拟节点时辨识虚拟节点。
如果在查找的过程中设置了属性 key , 那么查找速度会快很多。强烈建议在使用 v-for 时提供 key ,毕竟不加会输出警告。

<template>
    <div v-for="item in items" :key="item.id" >
            <!--内容-->
    <div/>
</template>

#2.在v-if/v-if-else/v-else 中使用key

如果一组v-if+v-else的元素类型相同,最好使用属性key(比如两个元素)。
如果添加了属性key,那么在对比虚拟DOM时,则会认为它们是两个同的节点,于是会将旧元素移除并在相同的位置添加一个新元素,从而避免意料之外的副作用。

<template>
    <div v-if="error" key="search-status"></div>
    <div v-else key="search-status"></div> 
</template>

#(五) 模板

#1.模板中简单的表达式

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

<template>
    <div>{{normaliFullName}}</div>
</template>
<script>
export default{
    computed:{
        normaliFullName:function(){
            return this.fullName.map(name=>{
            return name[0].toUpperCase() + name.slice(1)
            }).join(' ')
        }
}
}
</script>

#(六) 计算属性computed

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

<script>
export default{
    computed:{
        basePrice:function(){
            return this.manufacureCost / ( 1- this.profitMargin)
        },
        discount:function(){
            return this.manufacureCost * ( this.discountPercent || 0)
        }
    }
}
</script>

#(七) 指令

#1.指令缩写

指令缩写 ( 用 : 表示 v-bind: , @ 表示 v-on: ) 保持统一,要么都用,要么都不用

<template>
  <input type="text" 
    v-bind:value="name"
    v-on:focus="onFocus"
  />
 
  <input type="text" 
    :value="name"
    @focus="onFocus"
  />
</template>

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

当处理指令时,v-for 比 v-if 具有更高的优先级,所以即使我们只渲染出列表中的一小部分,也得在每次重渲染的时候遍历整个列表。

解决方案
  • 方案一: 使用计算属性过滤
<template>
    <div v-for="item in activeUser" :key="item.id" >
        <!--内容-->
    <div/>
</template>
<script>
computed:{
  activeUser:function(){
    return this.users.filter(user=>{
      return user.isActive
    })
  }
}
</script>
  • 方案二: 循环外层使用v-if
<template>
    <div v-if="status">
        <div v-for="item in items"></div>
    </div>
</template>

#没有在v-if/v-if-else/v-else中使用key

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

默认情况下,Vue 会尽可能高效的更新 DOM。这意味着其在相同类型的元素之间切换时,会修补已存在的元素,而不是将旧的元素移除然后在同一位置添加一个新元素。如果本不相同的元素被识别为相同,则会出现意料之外的副作用。

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

#(八) 私有属性名

在插件、混入等扩展中始终为自定义的私有属性使用 $_ 前缀。并附带一个命名空间以回避和其它作者的冲突 (比如 $yourPluginName)。

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

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

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

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

#(九) 带引号的特性值

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

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

#(十) 组件/实例

#1.选项的顺序

#(1)副作用 (触发组件外的影响)
  • el
#(2)全局感知 (要求组件以外的知识)
  • name
  • parent
#(3)组件类型 (更改组件的类型)
  • functional
#(4)模板修改器 (改变模板的编译方式)
  • delimiters
  • comments
#(5)模板依赖 (模板内使用的资源)
  • components
  • directives
  • filters
#(6)组合 (向选项里合并属性)
  • extends
  • mixins
#(7)接口 (组件的接口)
  • inheritAttrs
  • model
  • props / propsData
#(8)本地状态 (本地的响应式属性)
  • data
  • computed
#(9)事件 (通过响应式事件触发的回调)
  • watch
  • 生命周期钩子(按照它们被调用的顺序)
#(10)非响应式的属性 (不依赖响应系统的实例属性)
  • methods
#(11)渲染 (组件输出的声明式描述)
  • template / render
  • renderError

#(十一) 元素特性的顺序

#1.定义 (提供组件的选项)

  • is

#2.列表渲染 (创建多个变化的相同元素)

  • v-for

#3.条件渲染 (元素是否渲染/显示)

  • v-if
  • v-else-if
  • v-else
  • v-show
  • v-cloak

#4.渲染方式 (改变元素的渲染方式)

  • v-pre
  • v-once

#5.全局感知 (需要超越组件的知识)

  • id

#6.唯一的特性 (需要唯一值的特性)

  • ref
  • key
  • slot

#7.双向绑定 (把绑定和事件结合起来)

  • v-model

#8.其它特性 (所有普通的绑定或未绑定的特性)

#9.事件 (组件事件监听器)

  • v-on

#10.内容 (覆写元素的内容)

  • v-html
  • v-text

#(十二) 非Flux的全局状态管理

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

<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>
posted on   AtlasLapetos  阅读(15)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示