Nuxt 3组件开发与管理


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 = falseconst 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 的 actionsmutations

<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

在这个结构中,HeaderFooter 目录包含了与它们相关的子组件,而 HeroArticleList 是独立的组件。

模块化(Modularization)

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

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

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

composables/- useApi.js- useAuth.js- useUtils.jsstore/- index.jsutils/- 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.vuecomposables/- useHeader.js- useFooter.jsstore/- index.jsutils/- helpers.js

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

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 的布局,并在其中定义了一个包含 headermainfooter 的结构。在页面中,我们可以使用 <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 中常用的 createdbeforeDestroy 钩子,在 Vue 3 中仍然可以使用,但在 Nuxt 3 中,你可能会更倾向于使用 Composition API 中的生命周期函数。以下是它们在 Nuxt 3 中的对应:

  • created: 可以使用 onBeforeMountonMounted 代替,因为 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-lazyloadvue-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 中的 generatebuild 配置,控制预渲染的范围和时机。

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.js 深入浅出:目录结构与文件组织详解 | cmdragon’s Blog
  • 友情链接 | cmdragon’s Blog
  • 安装 Nuxt.js 的步骤和注意事项 | cmdragon’s Blog
  • 探索Web Components | cmdragon’s Blog
  • Vue微前端架构与Qiankun实践理论指南 | cmdragon’s Blog
  • Vue 3深度探索:自定义渲染器与服务端渲染 | cmdragon’s Blog
  • Tailwind CSS 响应式设计实战指南 | cmdragon’s Blog
  • Tailwind CSS 实战指南:快速构建响应式网页设计 | cmdragon’s Blog
  • Vue 3与ESLint、Prettier:构建规范化的前端开发环境 | cmdragon’s Blog
  • Vue TypeScript 实战:掌握静态类型编程 | cmdragon’s Blog
  • Vue CLI 4与项目构建实战指南 | cmdragon’s Blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/30995.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

源代码保密的七种有效方法分享

在当今数字化时代&#xff0c;访问安全和数据安全成为企业面临的重要挑战。传统的边界防御已经无法满足日益复杂的内网办公环境&#xff0c;层出不穷的攻击手段已经让市场单一的防御手段黔驴技穷。当企业面临越来越复杂的网络威胁和数据泄密风险时&#xff0c;更需要一种综合的…

多组学双疾病串扰怎么做?PAN-AD九个机器学习+MR+单细胞,工作量不少

说在前面 “串扰”这个名词听起来高级了一个level&#xff0c;其实就是MR-通路的双疾病联合分析。虽然是筛选标志物的思路&#xff0c;但是工作量不小&#xff0c;作者还收集了13个不同AD自身免疫疾病数据集用于验证自己的机器学习模型&#xff0c;分析就是一些常规的WGCNA、P…

SpringBoot集成logback初始化源码解析(部分)

一.SpringBoot配置扩展点 SpringBoot日志模块使用监听的方式进行初始化&#xff0c;在SpringBoot项目启动后&#xff0c;会通知日志监听器 在日志监听器中ApplicationStartingEvent事件用来确定到底使用哪个日志系统&#xff0c;logback log4j等 在日志监听器中ApplicationEn…

PTA - 编写函数计算薪资

某公司销售员底薪为5000&#xff0c;销售业绩与利润提成的关系如下表所示&#xff08;计量单位&#xff1a;元&#xff09; 编写函数&#xff0c;计算员工月薪。 函数接口定义&#xff1a; salary(sales) 其中 参数 sales表示员工的月销售业绩。 裁判测试程序样例&#xff…

管理咨询公司的五个招聘秘密

在管理咨询中&#xff0c;人是业务&#xff1b;客户支付数百万美元&#xff0c;要求管理顾问确认问题&#xff0c;并推荐解决方案。由于收入和合规性受到威胁&#xff0c;招聘错误的成本可能非常昂贵&#xff0c;一些公司更倾向于谨慎而不是效率。然而&#xff0c;在当今竞争激…

Java23种设计模式(五)

1、MVC 模式 MVC 模式代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。这种模式用于应用程序的分层开发。 Model&#xff08;模型&#xff09; - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑&#xff0c;在数据变化时更新控制器。…

第三期【Demo教程】教你使用SeaTunnel把数据从MySQL导到Hive

随着数据技术的快速发展&#xff0c;了解并掌握各种工具和技术变得尤为重要。为此&#xff0c;我们准备在Apache SeaTunnel社区发起如何使用连接器的Demo演示计划&#xff0c;邀请所有热爱数据同步技术的同学分享他们的知识和实操经验! 我们第三期主题是&#xff1a;如何使用Se…

Python MongoDB 基本操作

本文内容主要为使用Python 对Mongodb数据库的一些基本操作整理。 目录 安装类库 操作实例 引用类库 连接服务器 连接数据库 添加文档 添加单条 批量添加 查询文档 查询所有文档 查询部分文档 使用id查询 统计查询 排序 分页查询 更新文档 update_one方法 upd…

【Linux工具】yum软件包管理器与Vim编辑器的高效运用

目录 Linux 软件包管理器 YUM 什么是软件包 安装工具 rzsz 及注意事项 查看软件包 安装和卸载软件 安装软件 卸载软件 Linux 开发工具 编辑器 - Vim 使用 ​编辑 Vim 与 Vi 的区别 Vim 的基本概念 三种模式 Vim 的基本操作 操作尝试&#xff1a; Vim 命令集解释…

根据滚珠丝杆规格适配丝杆支撑座!

丝杆支撑座是机械设备中常见的支撑座装置&#xff0c;支撑着滚珠丝杆&#xff0c;起到稳定和支撑的作用&#xff0c;避免丝杆弯曲变形和震动&#xff0c;从而保证设备的稳定运行。那么&#xff0c;我们应该如何正确选择丝杆支撑座呢&#xff1f; 在选择丝杆支撑座时&#xff0c…

opencv 打开图片后,cv::mat存入共享内存的代码,实现消费者与生产者模型。XSI信号量和POSIX 信号量

文章目录 基于 sys 系统信号量(XSI信号量)常用api参考 基于 POSIX 信号量有名信号量常用 api 无名信号量常用 api 参考 实践-基于POSIX有名信号量生产者消费者模型任务说明同步关系互斥关系 设置一个互斥信号量&#xff0c;实现对共享内存的互斥访问设置两个信号量&#xff0c;…

铁路防鸟有哪些措施?铁路专用太阳能雷达驱鸟扇

铁路沿线的电杆、接触网支柱以及硬横梁等结构&#xff0c;因其牢固稳定以及无晃动的特点&#xff0c;成为了鸟儿们心仪的筑巢佳地&#xff0c;众多鸟类选择在此“安营扎寨”。而鸟巢中的树枝、草根和铁丝等杂物&#xff0c;极易引起铁路供电设备跳闸&#xff0c;导致短路停电&a…

【云岚到家】-day04-1-数据同步方案-Canal-MQ

【云岚到家】-day04-1-数据同步方案-Canal-MQ 1 服务搜索1.1 服务搜索技术方案1.1.1 需求分析1.1.2 技术方案1.1.2.1 使用Elasticsearch进行全文检索1.1.2.2 索引同步方案 1.1.3 CanalMQ1.1.3.1 MySQL主从数据同步1.1.3.2 Canal工作流程1.1.3.3 具体实现方案 1.2 MQ技术方案1.2…

【QT】

通信服务端实现 widget.h文件 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpServer>//服务器类 #include <QMessageBox>//消息 #include <QTcpServer> #include <QList> #include <QTcpSocket> QT_BEGIN_NAMESPAC…

我在高职教STM32——LCD液晶显示(2)

大家好&#xff0c;我是老耿&#xff0c;高职青椒一枚&#xff0c;一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次&#xff0c;同行应该都懂的&#xff0c;老师在课堂上教学几乎是没什么成就感的。正因如此&#xff0c;才有了借助 CSDN 平台寻求认同感和成就…

Linux源码学习笔记01-Linux内核源码结构

Linux内核特性 是一个类Unix操作系统&#xff0c;但不是简化的Unix&#xff1b;不仅继承了Unix的特征&#xff0c;还有其他特性。 Linux内核的组织形式&#xff1a;整体式的结构&#xff0c;方便每个领域的开发人员参与开发&#xff1b;Linux进程调度方式简单高效&#xff1a…

用智能插件(Fitten Code: Faster and Better AI Assistant)再次修改vue3 <script setup>留言板

<template><div><button class"openForm" click"openForm" v-if"!formVisible">编辑</button><button click"closeForm" v-if"formVisible">取消编辑</button><hr /><formv-i…

【权威发布】2024年环境科学、旅游与产业经济国际会议(ICESTIE 2024)

2024年环境科学、旅游与产业经济国际会议 2024 International Conference on Environmental Science, Tourism and Industrial Economics 会议简介 2024年环境科学、旅游与产业经济国际会议旨在汇聚全球该领域的专家学者&#xff0c;共同探讨环境科学与旅游产业的融合发展&…

SDK编译IO Domain电压选择

开源鸿蒙硬件方案领跑者 触觉智能 本文适用于在Purple Pi OH开发板进行分区镜像烧录。触觉智能的Purple Pi OH鸿蒙开源主板&#xff0c;是华为Laval官方社区主荐的一款鸿蒙开发主板。 该主板主要针对学生党&#xff0c;极客&#xff0c;工程师&#xff0c;极大降低了开源鸿蒙…

【iOS】#include、#import、@class、@import

文章目录 #include#importclassimport总结 #include #include是c\c中的预处理器指令&#xff0c;用于包含头文件的内容 但是使用#include可能会出现重复包含文件的问题&#xff0c;因此需要使用&#xff08;#ifndef/#define/#endif&#xff09;。 #import //导入系统头文件…