title: Nuxt 3组件开发与管理

date: 2024/6/20

updated: 2024/6/20

author: cmdragon

excerpt:

摘要:本文深入探讨了Nuxt 3的组件开发与管理,从基础概念、安装配置、目录结构、组件分类与开发实践、生命周期与优化,到测试与维护策略。详细介绍了Nuxt 3的核心特点,如服务器端渲染(SSR)、静态站点生成(SSG)以及与Vue生态系统的无缝集成。文章以Nuxt 3为基础,指导开发者如何高效构建高性能、可维护的Vue应用程序。内容涵盖了基本组件的定义与分类、独立组件与函数式组件的示例、Props和Slots的使用、Composition API的引入,以及组件的生命周期与优化方法。同时,文章还提供了组件开发的实践案例,包括自定义组件开发、异步加载组件、事件与方法的使用,以及组件测试与文档化指南。通过结构化的目录组织与详细的代码示例,旨在帮助开发者高效管理与维护组件,实现代码的复用与模块化。

categories:

  • 前端开发

tags:

  • Vue
  • Nuxt3
  • 组件开发
  • 管理策略
  • 生命周期
  • 性能优化
  • 测试文档

扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

第1章:Nuxt 3简介

1.1 Nuxt 3概述

1.1.1 什么是Nuxt.js Nuxt.js是一个基于Vue.js的开源框架,专为构建高性能、可维护的服务器渲染和静态站点生成应用而设计。Nuxt 3是其最新版本,它采用Vue 3和TSX(TypeScript的扩展)作为基础,提供了更简洁的API和更好的性能。

1.1.2 Nuxt 3特点

  • 服务器端渲染(SSR):提高SEO和初始加载速度。
  • 前端应用(SPA):现代的单页应用体验。
  • 静态站点生成(SSG):支持快速的静态内容部署。
  • 集成强大:与Vue生态系统无缝集成,如Vuex、Vuex-ORM等。

1.2 安装与配置

1.2.1 安装Nuxt 3 在命令行中运行以下命令安装Nuxt 3 CLI:

npm install -g npx
npx create-nuxt-app my-app

或者使用Yarn:

yarn global add create-nuxt-app
create-nuxt-app my-app

1.2.2 配置基本项目

  • 进入项目目录:cd my-app
  • 配置nuxt.config.ts:设置基础配置,如目标环境、SSR、SSG等。
// nuxt.config.ts
export default {
target: 'server', // 或者 'static', 根据需求选择
// 更多配置...
}

1.3 基本架构介绍

1.3.1 项目结构

  • pages:存放所有路由相关的组件,如pages/index.vue
  • components:存放可复用的Vue组件。
  • layouts:定义页面布局,如layouts/default.vue
  • plugins:全局或局部插件。
  • store:Vuex状态管理。

1.3.2 主要组件类型

  • Layouts: 共享的页面结构,如头部、尾部和主要内容区域。
  • Pages: 与特定路由关联的组件,处理业务逻辑和视图。
  • Modules: 对项目进行分模块管理,如API、状态管理等。

1.3.3 CLI命令

  • nuxt generate:生成静态站点。
  • nuxt start:启动开发服务器。
  • nuxt build:构建生产环境。

第2章:Nuxt 3组件基础

2.1 组件定义与分类

2.1.1 组件定义 在Nuxt 3中,组件是可复用的代码块,可以是Vue组件或自定义的函数式组件。Vue组件使用.vue文件扩展名,而函数式组件使用<script setup>语法。

2.1.2 组件分类

  • 独立组件(Single File Components, SFC):如.vue文件,包含模板、逻辑和样式。
  • 函数式组件(Functional Components):使用<script setup>,更简洁,侧重于逻辑和数据处理。
  • 组件库:预编译的组件集合,可以自定义或使用第三方库。

2.2 简单组件示例

2.2.1 独立组件示例

<!-- pages/components/Button.vue -->
<template>
<button :class="{ active: isActive }">{{ buttonText }}</button>
</template> <script>
export default {
props: {
buttonText: { type: String, required: true },
isActive: { type: Boolean, default: false }
}
}
</script>

2.2.2 函数式组件示例

<!-- pages/components/Button.vue -->
<script setup>
import { ref } from 'vue' const buttonText = ref('Click me')
const isActive = ref(false) function handleClick() {
isActive.value = !isActive.value
} function render() {
return <button :class="{ active: isActive.value }" @click={handleClick}>{buttonText.value}</button>
} export default {
render
}
</script>

2.3 Props和Slots的使用

2.3.1 Props(属性)

  • Props是组件间的通信方式,父组件向子组件传递数据。
  • props对象定义组件接受的属性,如上述按钮组件的buttonTextisActive

2.3.2 Slots(插槽)

  • Slots用于在组件中定义可替换的部分,父组件可以通过<slot>标签传递内容给子组件。
  • 子组件可以使用<template v-slot>来定义默认插槽或命名插槽。

2.4 使用Composition API

2.4.1 Refs(响应式引用)

  • Composition API引入了ref,用于创建响应式的变量,如上述isActivebuttonText

2.4.2 Setup Function(设置函数)

  • setup函数是组件的逻辑核心,替代了.vue文件中的export default部分,用于导入和导出函数、变量和方法。
<script setup>
import { ref } from 'vue' const count = ref(0) function increment() {
count.value++
} export default {
onMounted() {
// 在组件挂载后执行
},
methods: {
increment
}
}
</script>

第3章:组件开发实践

3.1 自定义组件开发

3.1.1 组件结构

在Nuxt 3中,自定义组件通常包含<template><script setup><style>部分。

  • <template>:定义组件的视图结构,包括HTML结构和模板指令。
  • <script setup>:定义组件的逻辑,包括数据、计算属性、方法、生命周期钩子等。
  • <style>:定义组件的样式,可以使用CSS、SCSS、LESS等。

例如,创建一个名为MyComponent.vue的自定义组件:

<template>
<div>
<h1>{{ title }}</h1>
<button @click="increment">Count: {{ count }}</button>
</div>
</template> <script setup>
import { ref, computed } from 'vue' const title = 'My Component'
const count = ref(0) const increment = () => {
count.value++
}
</script> <style>
h1 {
color: red;
}
</style>

3.1.2 组件实例

每个组件都有一个实例,可以通过this关键字访问组件内部的变量和方法。

<script setup>中,可以使用definePropsdefineEmitsdefineExpose等API来定义属性和方法。

例如,在上面的MyComponent.vue中,可以使用defineProps来定义title属性:

<script setup>
import { ref, computed, defineProps } from 'vue' const count = ref(0)
const increment = () => {
count.value++
} const props = defineProps({
title: {
type: String,
required: true
}
})
</script>

在父组件中,可以使用v-bind来传递title属性:

<template>
<div>
<MyComponent :title="'Custom Title'" />
</div>
</template>

3.2 异步加载组件

在 Nuxt 3 中,可以使用异步加载来延迟加载组件,从而提高应用程序的性能和用户体验。

3.2.1 动态导入

可以使用动态导入来异步加载组件。在<script setup>中,可以使用import关键字来动态导入组件:

<template>
<div>
<AsyncComponent v-if="showAsyncComponent" />
<button @click="showAsyncComponent = true">Load Async Component</button>
</div>
</template> <script setup>
import { ref } from 'vue' const showAsyncComponent = ref(false) const AsyncComponent = () => import('./AsyncComponent.vue')
</script>

在上面的例子中,AsyncComponent是一个动态导入的组件,只有在点击按钮时才会加载。

3.2.2 异步数据

如果组件需要加载异步数据,可以在<script setup>中使用async/await来加载数据,并在数据加载完成后渲染组件。

例如,在下面的例子中,AsyncDataComponent组件需要加载一个异步数据:

<template>
<div>
<AsyncDataComponent v-if="dataLoaded" :data="data" />
<button @click="loadData">Load Data</button>
</div>
</template> <script setup>
import { ref, defineAsyncComponent } from 'vue' const dataLoaded = ref(false)
const data = ref(null) const AsyncDataComponent = defineAsyncComponent(() =>
import('./AsyncDataComponent.vue')
) const loadData = async () => {
dataLoaded.value = false
const response = await fetch('https://api.example.com/data')
data.value = await response.json()
dataLoaded.value = true
}
</script>

在上面的例子中,点击按钮时会调用loadData方法,加载异步数据,并在数据加载完成后渲染AsyncDataComponent组件。

3.3 事件与方法

方法(Methods)

在 Nuxt 3 中,组件内的方法是通过在 <script setup> 或 <script> 标签中定义 methods 对象来实现的。这些方法可以在模板中被调用,也可以在组件内部的其他方法中被调用。

以下是一个简单的示例:

<template>
<button @click="increment">点击我</button>
<p>{{ count }}</p>
</template> <script setup>
import { ref } from 'vue'; const count = ref(0); const increment = () => {
count.value++;
};
</script>

在这个例子中,increment 方法会在点击按钮时被调用,使得 count 的值增加。

事件(Events)

自定义事件

组件可以通过 $emit 方法发出自定义事件,父组件可以通过监听这些事件来响应。

以下是如何在子组件中发出一个自定义事件的示例:

<template>
<button @click="sendEvent">发送事件</button>
</template> <script setup>
const emit = defineEmits(['custom-event']); const sendEvent = () => {
emit('custom-event', { message: 'Hello from child component!' });
};
</script>

父组件可以像这样监听这个事件:

<template>
<ChildComponent @custom-event="handleCustomEvent" />
</template> <script setup>
const handleCustomEvent = (payload) => {
console.log(payload.message); // 输出: Hello from child component!
};
</script>

原生事件

你还可以在组件上直接监听原生 DOM 事件,如下所示:

<template>
<input type="text" @input="handleInput" />
</template> <script setup>
const handleInput = (event) => {
console.log(event.target.value); // 输出输入框的值
};
</script>

使用 Vuex 中的事件和方法

如果在使用 Vuex 来管理状态,你可能会在组件中调用 Vuex 的 actions 或 mutations

<template>
<button @click="increment">增加</button>
</template> <script setup>
import { useStore } from 'vuex'; const store = useStore(); const increment = () => {
store.dispatch('increment');
};
</script>

在这个例子中,当按钮被点击时,会调用 Vuex store 中的 increment action。

第4章:组件组织与管理

4.1 组件目录结构

在 Nuxt.js 3.x 中,组件目录结构非常灵活,你可以根据项目需求自定义组件的存放位置。但是,为了保持代码结构的清晰和可维护,建议按照以下目录结构组织组件:

  1. 通用组件:将所有可复用的组件放在components目录中。例如:

    components/
    - Button.vue
    - Input.vue
    - Icon.vue
  2. 页面组件:每个页面组件都可以作为一个单独的.vue文件存在,并放在pages目录中。例如:

    pages/
    - index.vue
    - about.vue
    - products/
    - index.vue
    - product-1.vue
  3. 布局组件:布局组件可以放在layouts目录中。例如:

    layouts/
    - default.vue
    - admin.vue
  4. 插件:如果你需要在组件中使用第三方库或自定义插件,可以将它们放在plugins目录中。例如:

    plugins/
    - third-party.js
    - custom.js
  5. 模块:如果你需要在项目中使用自定义模块,可以将它们放在modules目录中。例如:

    modules/
    - custom-module.js

4.2 分级组件和模块化

在 Nuxt 3 中,组件化和模块化是两个核心概念,它们有助于构建可维护和可扩展的应用程序。以下是关于 Nuxt 3 中的分级组件和模块化的详细说明:

分级组件(Hierarchical Components)

分级组件指的是组件之间的嵌套关系,这种关系可以帮助我们构建复杂的用户界面。在 Nuxt 3 中,组件可以按照以下方式组织:

  1. 根组件:通常位于 pages 目录下的 .vue 文件,它们是页面的入口。
  2. 子组件:可以在页面组件中或其它组件中嵌套使用的组件。子组件通常放在 components 目录下,并可以进一步细分为子目录,以反映它们的功能或用途。

以下是一个分级组件的例子:

components/
- Header/
- Logo.vue
- Navigation.vue
- Footer/
- Contact.vue
- SocialLinks.vue
- Hero.vue
- ArticleList.vue

在这个结构中,Header 和 Footer 目录包含了与它们相关的子组件,而 Hero 和 ArticleList 是独立的组件。

模块化(Modularization)

模块化是一种将代码分解成可重用模块的方法,每个模块都专注于一个特定的功能。在 Nuxt 3 中,模块化可以通过以下方式实现:

  1. Nuxt 模块:Nuxt 3 支持通过 modules 目录或 nuxt.config.ts 文件自动注册本地或第三方模块。这些模块可以扩展 Nuxt 的核心功能或提供额外的工具。
  2. 可复用逻辑:将可复用的逻辑(如 API 调用、状态管理、工具函数)放在单独的文件或目录中,然后在需要的地方导入它们。

以下是一个模块化的例子:

composables/
- useApi.js
- useAuth.js
- useUtils.js store/
- index.js utils/
- helpers.js
- validators.js

在这个结构中,composables 目录包含了可复用的组合式函数,store 目录包含了状态管理逻辑,而 utils 目录包含了工具函数和验证器。

结合分级组件和模块化

在 Nuxt 3 中,你可以将分级组件和模块化结合起来,创建一个既清晰又易于维护的项目结构:

  • 使用分级组件来组织你的用户界面。
  • 使用模块化来组织你的应用逻辑。

通过这种方式,你可以确保每个组件都专注于展示逻辑,而模块则处理应用的业务逻辑,从而实现关注点分离。例如:

components/
- Header.vue
- Header/
- Logo.vue
- Navigation.vue
- Footer.vue
- Footer/
- Contact.vue
- SocialLinks.vue
- ArticleList.vue composables/
- useHeader.js
- useFooter.js store/
- index.js utils/
- helpers.js

在这个结构中,Header 和 Footer 组件可以导入对应的 useHeader 和 useFooter 组合式函数来获取所需的数据和逻辑。这样的组织方式有助于保持代码的清晰和可维护性。

4.3 使用Layouts和Modules

Nuxt 3 中的 Layouts 和 Modules 是两个重要的概念,它们可以帮助你构建更加灵活和可扩展的应用程序。以下是关于 Nuxt 3 中的 Layouts 和 Modules 的详细说明:

Layouts

Layouts 是一种在 Nuxt 中定义应用程序布局的方式,它们可以让你在不同页面之间共享相同的布局。在 Nuxt 3 中,你可以在 layouts 目录中创建自定义的布局。

以下是一个简单的 Layouts 示例:

  1. 创建一个名为 layouts 的目录,并在其中创建一个名为 default.vue 的文件:

    layouts/
    - default.vue
  2. 在 default.vue 文件中定义你的布局:

    <template>
    <div>
    <header>
    <h1>我的应用程序</h1>
    </header> <main>
    <slot />
    </main> <footer>
    <p> 2023 我的应用程序</p>
    </footer>
    </div>
    </template>
  3. 在你的页面中使用 Layouts:

    <template>
    <h2>我的页面</h2>
    <p>这是我的页面内容。</p>
    </template>

    在这个示例中,我们在 layouts 目录中创建了一个名为 default.vue 的布局,并在其中定义了一个包含 headermain 和 footer 的结构。在页面中,我们可以使用 <slot /> 插槽来显示页面的内容。

Modules

Modules 是一种在 Nuxt 中扩展应用程序功能的方式,它们可以让你在整个应用程序中使用自定义的功能或第三方插件。在 Nuxt 3 中,你可以使用 modules 目录或 nuxt.config.ts 文件来注册本地或第三方模块。

以下是一个简单的 Modules 示例:

  1. 创建一个名为 modules 的目录,并在其中创建一个名为 example.ts 的文件:

    modules/
    - example.ts
  2. 在 example.ts 文件中定义你的模块:

    import { ModuleOptions } from '@nuxt/types'
    
    export default function exampleModule(options: ModuleOptions) {
    this.nuxt.hook('render:route', (route) => {
    console.log(`渲染路由:${route.fullPath}`)
    })
    }

    在这个示例中,我们创建了一个名为 exampleModule 的函数,它接收一个 ModuleOptions 类型的参数。在函数中,我们使用 this.nuxt.hook 钩子函数来注册一个名为 render:route 的钩子,并在钩子函数中记录当前渲染的路由。

  3. 在 nuxt.config.ts 文件中注册你的模块:

    import { defineNuxtConfig } from 'nuxt'
    import exampleModule from './modules/example' export default defineNuxtConfig({
    modules: [
    exampleModule
    ]
    })

    在这个示例中,我们在 nuxt.config.ts 文件中使用 modules 数组来注册我们的 exampleModule 模块。

4.4 CSS模块化与 scoped CSS

CSS 模块化

CSS 模块化是一种将 CSS 文件与 JavaScript 文件耦合在一起的技术,它可以帮助你在构建应用程序时更好地管理和组织你的样式表。在 Nuxt.js 3.4 中,你可以使用 <style module> 标签来定义 CSS 模块。

以下是一个简单的 CSS 模块化示例:

  1. 创建一个名为 components 的目录,并在其中创建一个名为 MyComponent.vue 的文件:

    components/
    - MyComponent.vue
  2. 在 MyComponent.vue 文件中定义你的组件:

    <template>
    <div :class="$style.myComponent">
    <h2 :class="$style.title">我的组件标题</h2>
    <p :class="$style.content">我的组件内容。</p>
    </div>
    </template> <style module>
    .myComponent {
    border: 1px solid #ccc;
    padding: 16px;
    } .title {
    color: #333;
    font-size: 18px;
    margin-top: 0;
    } .content {
    color: #666;
    font-size: 14px;
    margin-bottom: 0;
    }
    </style>

    在这个示例中,我们在 MyComponent.vue 文件中使用 <style module> 标签来定义我们的 CSS 模块。在 CSS 模块中,我们可以使用 $style 对象来引用我们的样式类,并在组件的模板中使用这些类来应用样式。

scoped CSS

scoped CSS 是一种将样式限定在当前组件范围内的技术,它可以帮助你避免样式冲突和污染。在 Nuxt.js 3.4 中,你可以使用 scoped 属性来定义 scoped CSS。

以下是一个简单的 scoped CSS 示例:

  1. 创建一个名为 components 的目录,并在其中创建一个名为 MyComponent.vue 的文件:

    components/
    - MyComponent.vue
  2. 在 MyComponent.vue 文件中定义你的组件:

    <template>
    <div>
    <h2 class="title">我的组件标题</h2>
    <p class="content">我的组件内容。</p>
    </div>
    </template> <style scoped>
    .title {
    color: #333;
    font-size: 18px;
    margin-top: 0;
    } .content {
    color: #666;
    font-size: 14px;
    margin-bottom: 0;
    }
    </style>

    在这个示例中,我们在 MyComponent.vue 文件中使用 scoped 属性来定义我们的 scoped CSS。在 scoped CSS 中,我们可以使用普通的 CSS 类来定义样式,这些样式将只应用于当前组件。

第五章:组件生命周期与优化

Nuxt 3 中的生命周期钩子

Nuxt 3 是基于 Vue 3 的服务器端渲染(SSR)框架,它提供了一套完整的生命周期钩子,允许开发者在不同阶段对组件进行操作。在 Nuxt 3 中,生命周期钩子的使用与 Vue 3 相似,但由于其 SSR 的特性,有一些区别。以下是 Nuxt 3 中常用的生命周期钩子:

setup

setup 是 Vue 3 Composition API 的入口,它是一个选项,作为组件的入口点,在组件创建之前执行。在 Nuxt 3 中,你可以在 setup 函数中定义组件的响应式数据和逻辑。

export default defineComponent({
setup() {
const count = ref(0); // 逻辑代码... return { count };
}
});

服务器端渲染相关钩子

  • beforeRouteEnter: 在路由进入该组件的对应路由之前调用。
  • beforeRouteUpdate: 在当前路由改变,但是该组件被复用时调用。
  • beforeRouteLeave: 导航离开该组件的对应路由时调用。

客户端渲染相关钩子

以下是一些客户端特有的生命周期钩子:

  • onBeforeMount: 在组件挂载之前调用。
  • onMounted: 在组件挂载之后调用。
  • onBeforeUpdate: 在组件更新之前调用。
  • onUpdated: 在组件更新之后调用。
  • onBeforeUnmount: 在组件卸载之前调用。
  • onUnmounted: 在组件卸载之后调用。

created 和 beforeDestroy

在 Vue 2 中常用的 created 和 beforeDestroy 钩子,在 Vue 3 中仍然可以使用,但在 Nuxt 3 中,你可能会更倾向于使用 Composition API 中的生命周期函数。以下是它们在 Nuxt 3 中的对应:

  • created: 可以使用 onBeforeMount 或 onMounted 代替,因为 Nuxt 3 是基于 Vue 3 的,created 钩子在服务器端也会被调用,但它不保证在客户端执行。
  • beforeDestroy: 可以使用 onBeforeUnmount 代替。

以下是如何在 Nuxt 3 中使用 onBeforeUnmount 的示例:

export default defineComponent({
setup() {
onBeforeUnmount(() => {
console.log('组件即将被卸载');
}); // 其他逻辑...
}
});

在 Nuxt 3 中,由于它支持 Vue 3 的 Composition API,建议使用新的生命周期函数,它们提供了更细粒度的控制,并允许你在不同的生命周期阶段更清晰地组织代码。

5.2 性能优化:懒加载、预渲染

Nuxt 3 提供了多种性能优化策略,包括懒加载(Lazy Loading)和预渲染(Prerendering)。以下是关于这两个方面的简要介绍:

1. 懒加载(Lazy Loading)

Nuxt 3 的懒加载功能允许你只加载用户需要的部分内容,而不是一次性加载整个页面。这主要通过使用 vue-lazyload 或 vue-meta 等库,以及 Nuxt 的官方 nuxt-lazyload 插件来实现。

  • vue-lazyload: 可以在单个组件或整个页面上设置图片、子组件等元素的懒加载。
  • vue-meta: 可以配置路由的 <meta> 标签,控制路由的预加载和懒加载。
  • nuxt-lazyload: Nuxt 提供的官方插件,可以全局配置懒加载策略。

在 nuxt.config.js 中配置懒加载插件:

export default {
// ...
plugins: [
{ src: '~/plugins/nuxt-lazyload', ssr: false }, // ssr: false 表示在客户端执行懒加载
],
// ...
}

2. 预渲染(Prerendering)

Nuxt 3 支持两种预渲染方法:静态预渲染(Static Rendering)和服务器端渲染(Server-side Rendering,SSR)。

  • 静态预渲染(Static Rendering) : 使用 nuxt generate 命令生成静态 HTML 版本的页面,这些页面在服务器上预先加载和解析,提高首屏加载速度。这对于 SEO 有显著优势,但不支持实时更新。
  • 服务器端渲染(SSR) : 在用户访问页面时,Nuxt 会先在服务器上渲染整个页面,然后将渲染结果返回给客户端。这提供了更好的用户体验,尤其是对于动态内容,但服务器资源消耗较大。

为了优化 SSR,可以考虑以下策略:

  • 使用 nuxt optimize 命令进行性能分析和优化。
  • 避免在 SSR 中执行复杂的计算或网络请求。
  • 使用 nuxt.config.js 中的 generate 和 build 配置,控制预渲染的范围和时机。

5.3 代码复用与模块化策略

Nuxt 3 支持多种代码复用与模块化策略,以帮助开发人员提高代码的可重用性和可维护性。以下是一些常用的 Nuxt 3 模块化策略:

1. 共享组件(Shared Components)

在 Nuxt 3 中,可以将组件放在 components 目录下,这些组件可以在整个应用中共享使用。例如,创建一个 components/MyButton.vue 文件,其中包含一个自定义按钮组件:

<template>
<button @click="handleClick">
{{ label }}
</button>
</template> <script>
export default {
props: {
label: {
type: String,
default: 'Button',
},
},
methods: {
handleClick() {
this.$emit('click');
},
},
};
</script>

在其他组件中使用 MyButton 组件:

<template>
<div>
<MyButton label="Submit" @click="submitForm" />
</div>
</template> <script>
import MyButton from '~/components/MyButton.vue'; export default {
components: {
MyButton,
},
methods: {
submitForm() {
// ...
},
},
};
</script>

2. 插件(Plugins)

Nuxt 3 支持使用插件来扩展应用的功能。可以在 plugins 目录下创建插件文件,例如 plugins/my-plugin.js

export default function ({ app }) {
app.mixin({
methods: {
$myMethod() {
// ...
},
},
});
}

在 nuxt.config.js 中配置插件:

export default {
// ...
plugins: [
'~/plugins/my-plugin',
],
// ...
}

3. 模块(Modules)

Nuxt 3 支持使用模块来扩展应用的功能。可以在 modules 目录下创建模块文件,例如 modules/my-module.js

export default function (moduleOptions) {
this.nuxt.hook('components:dirs', (dirs) => {
dirs.push('~/components/my-module');
}); this.nuxt.hook('build:before', () => {
// ...
});
}

在 nuxt.config.js 中配置模块:

export default {
// ...
modules: [
'~/modules/my-module',
],
// ...
}

4. 布局(Layouts)

Nuxt 3 支持使用布局来实现页面的通用结构。可以在 layouts 目录下创建布局文件,例如 layouts/default.vue

<template>
<div>
<Header />
<main>
<slot />
</main>
<Footer />
</div>
</template> <script>
import Header from '~/components/Header.vue';
import Footer from '~/components/Footer.vue'; export default {
components: {
Header,
Footer,
},
};
</script>

在页面组件中使用布局:

<template>
<Layout>
<h1>My Page</h1>
</Layout>
</template>

5. 存储(Store)

Nuxt 3 支持使用 Vuex 实现应用的状态管理。可以在 store 目录下创建模块文件,例如 store/index.js

export const state = () => ({
count: 0,
}); export const mutations = {
increment(state) {
state.count++;
},
}; export const actions = {
async incrementAsync({ commit }) {
await new Promise((resolve) => setTimeout(resolve, 1000));
commit('increment');
},
}; export const getters = {
doubleCount(state) {
return state.count * 2;
},
};

在页面组件中使用存储:

<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
<button @click="incrementAsync">Increment Async</button>
</div>
</template> <script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'; export default {
computed: {
...mapState(['count']),
...mapGetters(['doubleCount']),
},
methods: {
...mapMutations(['increment']),
...mapActions(['incrementAsync']),
},
};
</script>

第6章:组件测试与维护

6.1 使用 Vue Test Utils 进行单元测试

Vue Test Utils 是 Vue.js 官方提供的测试工具库,用于编写 Vue.js 组件的单元测试。在 Nuxt 3 中,可以使用 Vue Test Utils 来测试组件的行为和状态。

首先,需要安装 Vue Test Utils 和一些其他依赖库:

npm install --save-dev @vue/test-utils vitest

然后,在项目根目录下创建一个 tests 目录,并在其中创建一个 unit 目录,用于存放单元测试文件。例如,测试 components/MyButton.vue 组件:

<template>
<button :class="buttonClass" @click="handleClick">
{{ label }}
</button>
</template> <script>
export default {
props: {
label: {
type: String,
default: 'Button',
},
type: {
type: String,
default: 'default',
},
},
computed: {
buttonClass() {
return {
'btn-primary': this.type === 'primary',
'btn-secondary': this.type === 'secondary',
};
},
},
methods: {
handleClick() {
this.$emit('click');
},
},
};
</script>

创建一个 tests/unit/MyButton.spec.js 文件,用于测试 MyButton 组件:

import { mount } from '@vue/test-utils';
import MyButton from '~/components/MyButton.vue'; describe('MyButton', () => {
it('renders correctly', () => {
const wrapper = mount(MyButton);
expect(wrapper.element).toMatchSnapshot();
}); it('emits click event when clicked', async () => {
const wrapper = mount(MyButton);
await wrapper.trigger('click');
expect(wrapper.emitted('click')).toBeTruthy();
}); it('applies primary class when type is primary', () => {
const wrapper = mount(MyButton, {
propsData: {
type: 'primary',
},
});
expect(wrapper.classes()).toContain('btn-primary');
}); it('applies secondary class when type is secondary', () => {
const wrapper = mount(MyButton, {
propsData: {
type: 'secondary',
},
});
expect(wrapper.classes()).toContain('btn-secondary');
});
});

最后,在 package.json 中配置测试命令:

{
"scripts": {
"test": "vitest"
}
}

运行测试命令:

npm test

6.2 使用 Storybook 进行组件开发与文档化

Storybook 是一个用于开发和文档化 UI 组件的工具。在 Nuxt 3 中,可以使用 Storybook 来开发和文档化组件。

首先,需要安装 Storybook 和一些其他依赖库:

npx sb init --builder @storybook/builder-webpack5 --typescript

然后,在项目根目录下创建一个 .storybook 目录,用于存放 Storybook 配置文件。例如,创建一个 .storybook/main.js 文件,用于配置 Storybook:

module.exports = {
stories: ['../components/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
],
framework: '@storybook/vue3',
core: {
builder: '@storybook/builder-webpack5',
},
};

在 components 目录下创建一个 MyButton.stories.ts 文件,用于定义 MyButton 组件的 Story:

import MyButton from './MyButton.vue';

export default {
title: 'Components/MyButton',
component: MyButton,
}; const Template = (args) => ({
components: { MyButton },
setup() {
return { args };
},
template: `
<MyButton v-bind="args" />
`,
}); export const Primary = Template.bind({});
Primary.args = {
label: 'Primary',
type: 'primary',
}; export const Secondary = Template.bind({});
Secondary.args = {
label: 'Secondary',
type: 'secondary',
};

最后,在 package.json 中配置 Storybook 命令:

{
"scripts": {
"storybook": "start-storybook -p 6006"
}
}

运行 Storybook 命令:

npm run storybook

6.3 维护与更新最佳实践

在 Nuxt 3 中开发和维护组件时,需要遵循一些最佳实践,以保证组件的可重用性和可维护性。

  1. 使用组件库:使用一些已有的组件库,如 Vuetify、Bootstrap-Vue 等,可以减少开发和维护的工作量。
  2. 使用组件 props:使用组件 props 可以使组件更加灵活和可重用。
  3. 使用组件 slot:使用组件 slot 可以使组件更加灵活和可扩展。
  4. 使用组件事件:使用组件事件可以使组件更加交互和可响应。
  5. 使用组件样式:使用组件样式可以使组件更加美观和一致。
  6. 使用组件测试:使用组件测试可以使组件更加可靠和可维护。
  7. 使用组件文档化:使用组件文档化可以使组件更加易于理解和使用。
  8. 使用组件更新:使用组件更新可以使组件更加新颖和有用。

往期文章推荐:

Nuxt 3组件开发与管理的更多相关文章

  1. day28 CRM万能权限组件开发 && 主机管理-堡垒机

    1,CRM项目实战-万能权限组件开发参考博客:http://www.cnblogs.com/alex3714/articles/6661911.html 参考代码:https://github.com ...

  2. [js开源组件开发]localStorage-cache本地存储的缓存管理

    localStorage-cache本地存储的缓存管理 距离上次的组件开发有近三个月的时间了,最近一直在做一些杂事,无法静下心来写写代码,也是在学习emberjs,在emberjs中有一个很重要的东西 ...

  3. 每天记录一点:NetCore获得配置文件 appsettings.json vue-router页面传值及接收值 详解webpack + vue + node 打造单页面(入门篇) 30分钟手把手教你学webpack实战 vue.js+webpack模块管理及组件开发

    每天记录一点:NetCore获得配置文件 appsettings.json   用NetCore做项目如果用EF  ORM在网上有很多的配置连接字符串,读取以及使用方法 由于很多朋友用的其他ORM如S ...

  4. React-Native 组件开发方法

    前言 React Native的开发思路是通过组合各种组件来组织整个App,在大部分情况下通过组合View.Image等几个基础的组件,可以非常方便的实现各种复杂的跨平台组件,不过在需要原生功能支持. ...

  5. 饿了么基于Vue2.0的通用组件开发之路(分享会记录)

    Element:一套通用组件库的开发之路 Element 是由饿了么UED设计.饿了么大前端开发的一套基于 Vue 2.0 的桌面端组件库.今天我们要分享的就是开发 Element 的一些心得. 官网 ...

  6. javascript组件开发之基类继承实现

    上一篇文章大概的介绍了一下关于javascript组件的开发方式,这篇文章主要详细记一下基类的编写,这个基类主要是实现继承的功能 为什么要封装基类? 由于这次重构项目需要对各种组件进行封装,并且这些组 ...

  7. javascript组件开发

    最近忙于重构项目,今天周末把在重构中的一些思想记记: 一.javascript的组件开发:基类的封装 由于这次重构项目需要对各种组件进行封装,并且这些组件的实现方式都差不多,所以想到对组件封装一个ba ...

  8. Agile.Net 组件式开发平台 - 组件开发示例

    所谓组件式开发平台,它所有的功能模块都是以组件的形式扩展的,下面我来演示一个简单的组件开发例程. Agile.Net开发管理平台项目,已经托管在开源中国码云平台(http://git.oschina. ...

  9. 基于GBT28181:SIP协议组件开发-----------第三篇SIP注册流程分析实现

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125. 上两章节简要的 ...

  10. ASP.NET自定义控件组件开发 第一章 第三篇

    原文:ASP.NET自定义控件组件开发 第一章 第三篇 第三篇:第一章的完结篇 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待 ...

随机推荐

  1. dotnet 在 WPF 里显示数学 π 的颜色

    有逗比小伙伴问我,数学的 π 视觉效果是啥.于是我就来写一个逗比的应用将 π 的颜色在 WPF 应用画出来.原理就是读取 π 的小数点后的数值,然后使用逗比算法转换为 RGB 颜色像素,接着将这些像素 ...

  2. 服务端向客户端发送消息Server-Sent Events

    今天听说了服务端向客户端发消息的一种方式:Server-Sent Events SSE使用的是HTTP协议,本质上是服务端向客户端发送流式数据. HTTP不支持服务端向客户端发送请求,但是如果客户端向 ...

  3. 【Linux】XFS文件系统

    XFS WIKI介绍 XFS is a high-performance 64-bit journaling file system created by Silicon Graphics, Inc ...

  4. gRPC入门学习之旅(八)

    gRPC入门学习之旅(一) gRPC入门学习之旅(二) gRPC入门学习之旅(三) gRPC入门学习之旅(四) gRPC入门学习之旅(五) gRPC入门学习之旅(六) gRPC入门学习之旅(七) 3. ...

  5. 4G EPS 的架构模型

    目录 文章目录 目录 前文列表 EPS 的架构 EPS 的架构模型 E-UTRAN UE eNodeB EPC MME(移动性管理) SGW(本地移动性锚点) PGW(业务锚点) HSS(用户认证及鉴 ...

  6. 一次nginx文件打开数的问题排查处理

    现象:nginx域名配置合并之后,发现consul-template无法完成nginx重载,然后发现需要重启nginx,才能让配置生效. 注意:下次哪个服务有报错,就看重启时所有日志输出,各种情况日志 ...

  7. Python:Python中的参数屏蔽

    我们有时会不经意间写下如下代码: def update_indices(indices): indices = [] # 像在更新indices前先将其置空 for i in range(10): i ...

  8. 本地项目文件上传到git

    初始化项目: git init 与服务器项目关联:git remote add origin "http://**************************/r/ruoyi.git&q ...

  9. python垃圾回收和缓存管理

    Python垃圾回收和缓存管理 你有没有想过为什么我们频繁地使用Python敲代码做项目,实际上一直在生产对象并不断占用内存,而我们很少会去清理Python的内存,理论上来讲它总有一天把内存消耗殆尽( ...

  10. golang 切片原理面试题

    package main import "fmt" func main() { var s = make([]int, 0, 10) _ = append(s, 1,2,3) fm ...