Nuxt 3組件開發與管理

来源:https://www.cnblogs.com/Amd794/p/18258611
-Advertisement-
Play Games

摘要:本文深入探討了Nuxt 3的組件開發與管理,從基礎概念、安裝配置、目錄結構、組件分類與開發實踐、生命周期與優化,到測試與維護策略。詳細介紹了Nuxt 3的核心特點,如伺服器端渲染(SSR)、靜態站點生成(SSG)以及與Vue生態系統的無縫集成。文章以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
  • 組件開發
  • 管理策略
  • 生命周期
  • 性能優化
  • 測試文檔

image

image

掃碼關註或者微信搜一搜:編程智域 前端至全棧交流與成長

第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. 使用組件更新:使用組件更新可以使組件更加新穎和有用。

往期文章推薦:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ‍ 寫在開頭 點贊 + 收藏 學會 如何解決uniapp H5本地代理實現跨域訪問? 1.第一種解決方法: 直接創建一個vue.config.js文件,併在裡面配置devServer,直接上代碼,重啟跑項目 親測有效 // vue.config.js module.exports ...
  • 很久很久沒有更新博客了,因為實在是太忙了,每天都有公司的事情忙不完....... 最近在做車輛模擬地圖,在實現控制站點名稱按需顯示時,折騰了好一段時間,特此記錄一下。最終界面如下圖所示: 站點顯示需求:首末站必須顯示,從第一個站開始,如果站點名稱能顯示下,則顯示,如果站點名稱會重疊則隱藏,以此類推。 ...
  • 摘要:本文是一份關於Nuxt 3路由系統的詳盡指南。它從介紹Nuxt 3的基本概念開始,包括Nuxt 3與Nuxt 2的區別和選擇Nuxt 3的理由。然後,它詳細解釋了安裝和配置Nuxt 3的步驟,以及Nuxt 3路由系統的基礎知識,如動態路由和嵌套路由。接著,它介紹了路由中間件的作用和編寫自定義中... ...
  • 最近需要做一個三維場景切換的功能,切換場景後,還可以進行二三維模式的切換,二三維切換時,要定位到當前場景視角,那麼場景的視角參數信息就需要保存到狀態數據中,以供二三維場景切換時使用。 項目是用vue做的,這裡並沒有使用vue的狀態管理庫,我是這樣實現的: 定義狀態數據sceneInfo let sc ...
  • 你習慣在js代碼中使用async await嗎? 我經常在js代碼中寫一些非同步方法,使用await調用的地方,如果方便修改成非同步方法,就修改成非同步方法,如下所示: async setPosition(graphic, lng, lat) { this.lng = lng; this.lat = la ...
  • 你不知道的 CSS 之包含塊 一說到 CSS 盒模型,這是很多小伙伴耳熟能詳的知識,甚至有的小伙伴還能說出 border-box 和 content-box 這兩種盒模型的區別。 但是一說到 CSS 包含塊,有的小伙伴就懵圈了,什麼是包含塊?好像從來沒有聽說過這玩意兒。 好吧,如果你對包含塊的知識一 ...
  • 作為一名前端開發者,vscode想必大家應該都接觸過,就像大多數 IDE 一樣,VSCode 也有一個擴展和主題市場,包含了數以千計質量不同的插件。 作為一名熟練掌握各種前端開發工具安裝和卸載的大師兄來說,為大家安利好玩有用的工具插件是我義不容辭的責任,所以我精挑細選了九款必備的vscode插件 C ...
  • ‍ 寫在開頭 點贊 + 收藏 學會 需求背景 從第三方採購的vue2 + ElementUI實現的雲管平臺,乙方說2011年左右就開始有這個項目了(那時候有Vue了嗎,思考.jpg)。十幾年的項目,我何德何能可以擔此責任。裡面的代碼經過多人多年迭代可以用慘不忍睹來形容,吐槽歸吐槽 ...
一周排行
    -Advertisement-
    Play Games
  • 問題 有很多應用程式在驗證JSON數據的時候用到了JSON Schema。 在微服務架構下,有時候各個微服務由於各種歷史原因,它們所生成的數據對JSON Object屬性名的大小寫規則可能並不統一,它們需要消費的JSON數據的屬性名可能需要大小寫無關。 遺憾的是,目前的JSON Schema沒有這方 ...
  • 首先下載centos07鏡像,建議使用阿裡雲推薦的地址: https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spm=a2c6h.25603864.0.0.59b5f5ad5Nfr0X 其實這裡就已經出現第一個坑了 centos 07 /u ...
  • 相信很多.NETer看了標題,都會忍不住好奇,點進來看看,並且順便準備要噴作者! 這裡,首先要申明一下,作者本人也非常喜歡Linq,也在各個項目中常用Linq。 我愛Linq,Linq優雅萬歲!!!(PS:順便吐槽一下,隔壁Java從8.0版本推出的Streams API,抄了個四不像,一點都不優雅 ...
  • 在人生的重要時刻,我站在了畢業的門檻上,望著前方的道路,心中涌動著對未來的無限憧憬與些許忐忑。面前,兩條道路蜿蜒伸展:一是繼續在職場中尋求穩定,一是勇敢地走出一條屬於自己的創新之路。儘管面臨年齡和現實的挑戰,我仍舊選擇勇往直前,用技術這把鑰匙,開啟新的人生篇章。 迴首過去,我深知時間寶貴,精力有限。 ...
  • 單元測試 前言 時隔多個月,終於抽空學習了點新知識,那麼這次來記錄一下C#怎麼進行單元測試,單元測試是做什麼的。 我相信大部分剛畢業的都很疑惑單元測試是乾什麼的?在小廠實習了6個月後,我發現每天除了寫CRUD就是寫CRUD,幾乎用不到單元測試。寫完一個功能直接上手去測,當然這隻是我個人感受,僅供參考 ...
  • 一:背景 1. 講故事 最近在分析dump時,發現有程式的卡死和WeakReference有關,在以前只知道怎麼用,但不清楚底層邏輯走向是什麼樣的,藉著這個dump的契機來簡單研究下。 二:弱引用的玩法 1. 一些基礎概念 用過WeakReference的朋友都知道這裡面又可以分為弱短和弱長兩個概念 ...
  • 最近想把ET打表工具的報錯提示直接調用win系統彈窗,好讓策劃明顯的知道表格哪裡填錯數據,彈窗需要調用System.Windows.Forms庫。操作如下: 需要在 .csproj 文件中添加: <UseWindowsForms>true</UseWindowsForms> 須將目標平臺設置為 Wi ...
  • 從C#3開始,拓展方法這一特性就得到了廣泛的應用。 此功能允許你能夠使用實例方法的語法調用某個靜態方法,以下是一個獲取/創建文件的靜態方法: public static async Task<StorageFile> GetOrCreateFileAsync(this StorageFolder f ...
  • 在Windows 11下,使用WinUI2.6以上版本的ListView長這樣: 然而到了Win10上,儘管其他控制項的樣式沒有改變,但ListViewItem變成了預設樣式(初代Fluent) 最重大的問題是,Win10上的HorizontalAlignment未被設置成Stretch,可能造成嚴重 ...
  • 前言 周六在公司加班,幹完活後越顯無聊,想著下載RabbiitMQ做個小項目玩玩。然而這一下就下載了2個小時,真讓人頭痛。 簡單的講一下如何安裝吧,網上教程和踩坑文章還是很多的,我講我感覺有用的文章放在本文末尾。 安裝地址 erlang 下載 - Erlang/OTP https://www.erl ...