Vue3编码规范

摘要

可读性高的代码,能减少代码理解的难度,在团队开发过程中,能有效的提高代码的可维护性,减少屎山代码.太过随意的代码,往往最容易形成屎山.

一、使用composition api来编码

按功能块写代码,不要想着data、methods
  • vue3就用composition api的思想来组织代码接口,按功能块写,抛弃vue2拆分datamethodscomputed 、生命函数分开写的思想

  • 避免将响应式变量ref声明全部写在一个地方,要按功能分开写

  • composition api是灵活多变的,功能A可以将ref/函数/watch/computed/生命周期函数写在一块,这样更容易维护

按功能块写法对比:
  • 不规范写法

listlist2所有的变量声明都放在一块了

        <script lang="ts" setup  name="test">
        import * as api from '@/api/table'
        let list = ref([
          { a: 1, b: 2, c: 3 },
          { a: 1, b: 2, c: 3 }
        ])
        let list2 = ref([
          { a: 1, b: 2, c: 3 },
          { a: 1, b: 2, c: 3 }
        ])
        const getList = async () => {
          try {
            let res = await api.saveTableApi({})
            list.value = res
          } catch (error) {}
        }

        const getList2 = async () => {
          try {
            let res = await api.saveTableApi({})
            list2.value = res
          } catch (error) {}
        }

        onMounted(() => {
          getList()
          getList2()
        })
        </script>
  • 按功能块写
        <script lang="ts" setup >
        import * as api from '@/api/table'
        //功能1    
        let list = ref([
          { a: 1, b: 2, c: 3 },
          { a: 1, b: 2, c: 3 }
        ])

        const getList = async () => {
          try {
            let res = await api.saveTableApi({})
            list.value = res
          } catch (error) {}
        }
        onMounted(() => {
          getList()
        })
        //功能2
        let list2 = ref([
          { a: 1, b: 2, c: 3 },
          { a: 1, b: 2, c: 3 }
        ])
        const getList2 = async () => {
          try {
            let res = await api.saveTableApi({})
            list2.value = res
          } catch (error) {}
        }
        onMounted(() => {
          getList2()
        })
        </script>

二、 使用setup语法糖 <script setup>编写组件

setup语法糖必须掌握的api:

  • defineProps() 和 defineEmits()
  • defineModel()
  • defineExpose()
  • defineOptions()

三、使用ref避免使用reactive 声明响应式数据

  • ref是官方推荐的声明响应式数据的API,可以声明基本数据类型和引用数据类型

  • 携带.value 尾巴,能直观展示是响应式数据

  • vscode 的Vue-official插件可开启对ref声明的响应式数据自动添加.value

四、Vue3一些Api技巧

v-forv-if同时使用时,巧妙使用template

v-forv-if是不能同时使用的,但是有些情况需要在遍历的时候判断能否展示

<ul>
  <template v-for="user in users" :key="user.id">
    <li v-if="user.isActive">
      {{ user.name }}
    </li>
  </template>
</ul>
组件间通讯

组件通讯的多种形式:

通讯方式api
父传子props/defineProps
父传子provide/inject
父子互相通讯v-model/defineModel
父组件访问子组件ref/defineExpose
子传父@/defineEmits

v-model/defineModel:

其中 v-model/defineModel是vue3.4版本后新出的api,解决了props/defineProps通讯是单向传值的问题, v-model/defineModel在子组件修改父组件的值也能做到双向绑定

父组件

<UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>

子组件

<template>
  <input type="text" v-model="firstName" />
  <input type="text" v-model="lastName" />
</template>

<script setup>

const firstName = defineModel('firstName')
const lastName = defineModel('lastName')    
</script>

provide/inject:

provide/inject依赖注入,可以在父组件中provide注入函数或者属性,在子组件还子孙组件中通过inject即可拿到父组件/祖先组件传递过来的函数或者属性,解决了props/defineProps逐层传递的弊端

//父组件 Root.vue---------------------------------------------------
<template>
  <div>
    <Footer/>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import Footer from './Footer.vue' //导入子组件Footer
//父组件中注册给共享后代组件的信息
provide(/* 注入名 */ 'mgs', /* 值 */ '父组件信息!')  

</script>

//子组件 Footer.vue--------------------------------------------------
<template>
    <DeepChild/>
</template>
<script setup>
import DeepChild from './DeepChild.vue' //导入子组件Footer
//在子组件Footer中可以不需要接收父组件Root共享的数据,在后代组件中,直接接收,实现跨级传递
</script>

//子孙组件DeepChild.vue---------------------------------------------------
<template>
    <div>
        {{ msg }}
    </div>
</template>
<script setup>
import { inject } from 'vue'
const msg = inject('msg') //跨级接收祖先组件的共享的信息
console.log(msg) //父组件信息
</script>
样式穿透修改UI组件库样式

需要样式穿透的原因:使用 scoped 后,父组件的样式将不会渗透到子组件中,这就为什么有时候修改UI组件库的样式不生效的原因

vue3的样式穿透: :deep(.想要穿透样式的classid)

<style lang="scss" scoped>
// 在scoped下这种修改UI组件库的方式不一定生效
.el-form {
    .el-form-item { ... }
}

// 需要使用样式穿透
:deep(.el-form) {
    .el-form-item { ... }
}
</style>
没了this,我只想this怎么办(不推荐用)

对于写Vue3还想着this的同学,我的评价是再多看一下Vue3官方文档,Vue3提供的composition api在绝大多情况下已经适用了

Vue3提供了getCurrentInstance替代this:

<script setup>
import { getCurrentInstance } from 'vue'

// proxy 就是当前组件实例,可以理解为组件级别的 this,没有全局的、路由、状态管理之类的
const { proxy, appContext } = getCurrentInstance()

// 这个 global 就是全局实例
const global = appContext.config.globalProperties
</script>
接口请求多使用async/await,配合try-catch使用

async/await的使用,能让异步请求变成更符合人类思维的同步操作,更方便组织代码,在try-catch 对异步的错误进行捕获,

<script setup>
const loading = ref(false)
const products = ref(null)

const init = async () => {
    loading.value = true
    try {
        products.value = await getProducts() //产品请求接口函数
    } catch (e) {
    }
    loading.value = false
}

onMounted(() => {
    init()
})
</script>

五、组件名称规范:

使用大驼峰/PascalCase命名组件,兼容性强
<template>
     <!-- 实例化组件方式1 -->
    <MyComponent/>
     <!-- 实例化组件方式2 -->
    <my-component/>
</template>
<script setup>
    import MyComponent from './MyComponent'
</script>
紧密耦合的组件名称:

与其父组件紧密耦合的子组件应包含父组件名称作为前缀。

命名规则: 父组件名称+子组件名称

好处:

  • 关系更紧密,通过看组件名即可知道2个组件的联系

  • 编辑器友好,例如VsCode,通常按字母顺序组织文件,因此这也使这些相关文件彼此相邻;

对比:

不推荐

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

推荐

components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
组件名称使用完整单词命名

对比:

不推荐

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

推荐

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

六、路由设置的path和组件的路径保持一致

好处: 通过url上的路径就能直接找到组件在项目中的位置

七、hooksutilsconstantstypes、API 等文件,就近存放,必要时才做目录提升

不能公共使用的都放在当前组件目录下,如果和业务关联性很大的不能复用的代码,写在公共目录下,就是对公共代码的污染

  |- 组件目录
    |- Index.vue 组件
    |- common  该组件下的工具方法
    	|- hooks.ts   
    	|- utils.ts
    	|- types.ts
    	|- constants.ts
    	|- API.ts

当然这里说的API.ts是已经使用axios统一封装好的业务接口,如下

//全局的接口请求封装
import request from '@/axios'

// 获取列表接口
export const getXXList = () => {
  return request.get({ url: '/mock/xx/list' })
}

为什么API.ts业务接口请求不是放在公共api目录下,而是推荐放在业务代码目录下?

在企业项目中业务量是庞大的,那么API目录可能会变得非常庞大,难以维护,出现以下情况:

  1. API目录下的业务api请求js文件过于庞大,如果文件夹语意不明确,根本无法知道是属于哪个业务的

  2. API目录下的业务api请求js,正常情况都是与业务紧密关联的,统一放在API目录下降低了代码的可读性

单独放在业务目录下的好处:

  • 方便跳转,在该业务目录下即可直达业务api请求js文件,方便维护
  • api接口与业务联系更紧密,提高了代码可读性,

八、 写TS不要写成any TS,减少any的使用

由于前端的小伙伴,写惯了js这种弱类型的语言,不知道强类型语言配合vscode这类代码编辑器的好处,比如类型检查代码提示

九、避免过渡封装

团队开发过程中,好用的封装是必不可少的,但是过度的封装,我个人是不推荐的,如果真要封装,我要做以下2点

  • 写好封装组件的使用说明文档

  • 文档第一条就写清楚,封装的好处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zqwang888

一毛不嫌少,一块不嫌多!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值