如何写出干净的组件

如何写出干净的组件

全局单例状态

我们写组件时,有时会遇到需要将数据通过 props 层层向下传递,或者是 emit 通过事件层层向上传递的情况。或者会遇到同级组件之间需要共享一些数据。

为了避免这种情况,我们可以使用全局单例状态来管理数据。

当然在 Vue3 中,我们可以使用 Pinia 来进行此操作。

useSettings.tsts
import { ref, toRefs } from 'vue'

const globalState = ref({
    darkMode: false,
    sidebarCollapsed: false,
    theme: 'green',
})

export default () => {
    // 一些逻辑处理

    return {
        ...toRefs(globalState)
    }
}
vue
<script setup lang="ts">
import useSettings from '@/composables/useSettings'

const { darkMode, sidebarCollapsed, theme } = useSettings()
function toggleDarkMode() {
    darkMode.value = !darkMode.value
}
</script>

传递整个对象

  1. 将整个数据对象作为 prop 传递,而不是逐个字段传递。我们经常会遇到添加一些字段到组件中,这样会导致 props 的数量不断增加。 为了避免这种情况,我们可以将整个对象传递给组件。
  2. 这样我们可以复用 TypeScript 的类型定义到组件中。

之前

vue
<template>
    <Article
        :title="article.title"
        :content="article.content"
    />
</template>
Article.vuevue
<script setup lang="ts">
import { IArticle } from '@/types/article'

const props = defineProps<{
    title: IArticle['title']
    content: IArticle['content']
}>()
</script>

<template>
<!-- 内部实现 -->
</template>

之后

vue
<template>
    <Article :article="article" />
</template>
Article.vuevue
<script setup lang="ts">
import { IArticle } from '@/types/article'

const props = defineProps<{
    article: IArticle
}>()
</script>

<template>
<!-- 内部实现 -->
</template>

如果此时我们的 article 要增加一个创建日期的字段,旧的写法需要修改 Article.vue 的 props 定义,而新的写法只需要修改 Article.vue 的展示逻辑即可(因为我们的类型是全局复用的)。

使用不同的组件处理 v-if 分支

vue
<template>
    <div v-if="showSomething">
        <div>一些代码,很长很长</div>
    </div>
    <div v-else>
        <div>另一些代码,很长很长</div>
    </div>
</template>
vue
<template>
    <div v-if="showSomething">
        <ComponentA />
    </div>
    <div v-else>
        <ComponentB />
    </div>
</template>

每一个分支都会做不同的事,所以将他们拆分成不同的组件是更好的选择。 这样不仅会使每个组件专注于特定的任务,还可以提高代码的可读性和可维护性。

将使用 v-for 的组件提取成 List 组件单独维护

有时候我们并不关心组件的循环的细节,我们可以将它提取成一个 List 组件来单独维护。

Before

vue
<template>
    <Article v-for="article in articles" :key="article.id" :article="article" />
</template>

After

vue
<template>
    <ArticleList :articles="articles" />
</template>
使用 chatgpt 制作自己的小贴纸
使用 caddy 替换 nginx

评论区

评论加载中...