Nuxt.js 指南

Nuxt.js 指南

目录

简介

Nuxt.js 是一个基于 Vue.js 的开源框架,它使得创建通用应用变得简单。它预设了利用 Vue.js 开发服务端渲染应用所需要的各种配置,同时也可以生成静态站点。

Nuxt.js 的主要特性

  • 自动路由配置
  • 服务端渲染 (SSR)
  • 静态站点生成 (SSG)
  • 代码分割
  • 中间件支持
  • 布局系统
  • 数据获取
  • 状态管理
  • SEO 优化

环境准备

系统要求

  • Node.js 12.x 或更高版本
  • npm 或 yarn 包管理器

安装 Nuxt.js

# 使用 npx
npx create-nuxt-app my-project

# 或使用 yarn
yarn create nuxt-app my-project

安装过程中的选项

  1. 项目名称
  2. 包管理器 (npm/yarn/pnpm)
  3. UI 框架 (Bootstrap, Tailwind, Vuetify 等)
  4. Nuxt.js 模块 (Axios, PWA 等)
  5. 代码规范工具 (ESLint, Prettier 等)
  6. 测试框架 (Jest, AVA 等)
  7. 渲染模式 (Universal/SSR, SPA, Static)
  8. 部署目标 (Server, Static)
  9. 开发工具 (jsconfig.json)
  10. Git 初始化

项目创建

基本项目结构

my-project/
├── assets/          # 未编译的静态资源
├── components/      # Vue 组件
├── layouts/         # 布局组件
├── middleware/      # 中间件
├── pages/           # 页面组件
├── plugins/         # 插件
├── static/          # 静态文件
├── store/           # Vuex 存储
├── nuxt.config.js   # Nuxt.js 配置
└── package.json     # 项目依赖

启动开发服务器

# 开发模式
npm run dev

# 构建生产版本
npm run build

# 启动生产服务器
npm run start

# 生成静态项目
npm run generate

项目结构

1. pages 目录

pages 目录中的文件会自动生成路由配置。

<!-- pages/index.vue -->
<template>
  <div>
    <h1>首页</h1>
  </div>
</template>

<script>
export default {
  name: 'HomePage'
}
</script>

2. components 目录

组件可以全局注册,无需导入即可使用。

<!-- components/Button.vue -->
<template>
  <button class="btn" @click="$emit('click')">
    <slot></slot>
  </button>
</template>

<script>
export default {
  name: 'Button'
}
</script>

3. layouts 目录

布局文件用于定义页面模板。

<!-- layouts/default.vue -->
<template>
  <div>
    <header>
      <nav>
        <NuxtLink to="/">首页</NuxtLink>
        <NuxtLink to="/about">关于</NuxtLink>
      </nav>
    </header>
    <main>
      <Nuxt />
    </main>
    <footer>
      <p>© 2023 My Nuxt App</p>
    </footer>
  </div>
</template>

4. assets 目录

存放需要编译的资源文件。

/* assets/scss/main.scss */
$primary-color: #42b983;

.btn {
  background-color: $primary-color;
  color: white;
  padding: 10px 20px;
  border-radius: 4px;
}

5. static 目录

存放不需要编译的静态文件。

static/
├── favicon.ico
├── robots.txt
└── images/
    └── logo.png

路由系统

1. 基本路由

pages 目录结构自动生成路由:

pages/
├── index.vue         # /
├── about.vue         # /about
├── users/
│   ├── index.vue     # /users
│   └── _id.vue       # /users/:id
└── _slug.vue         # /:slug

2. 动态路由

使用下划线前缀创建动态路由:

<!-- pages/users/_id.vue -->
<template>
  <div>
    <h1>用户详情</h1>
    <p>用户 ID: {{ $route.params.id }}</p>
  </div>
</template>

<script>
export default {
  validate({ params }) {
    return /^\d+$/.test(params.id)
  }
}
</script>

3. 嵌套路由

使用目录结构创建嵌套路由:

pages/
└── parent/
    ├── index.vue     # /parent
    └── child.vue     # /parent/child

4. 路由中间件

在页面组件中使用中间件:

<!-- pages/admin/index.vue -->
<template>
  <div>
    <h1>管理面板</h1>
  </div>
</template>

<script>
export default {
  middleware: 'auth'
}
</script>

数据获取

1. asyncData 方法

在页面组件渲染前获取数据:

<!-- pages/posts/index.vue -->
<template>
  <div>
    <h1>文章列表</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  async asyncData({ $axios }) {
    const posts = await $axios.$get('https://api.example.com/posts')
    return { posts }
  }
}
</script>

2. fetch 方法

在 store 中获取数据:

<!-- pages/posts/index.vue -->
<template>
  <div>
    <h1>文章列表</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState(['posts'])
  },
  fetch({ store }) {
    return store.dispatch('posts/fetchPosts')
  }
}
</script>

3. 使用 Axios 模块

配置 Axios 模块:

// nuxt.config.js
export default {
  modules: [
    '@nuxtjs/axios'
  ],
  axios: {
    baseURL: 'https://api.example.com'
  }
}

状态管理

1. Vuex 存储

创建 Vuex 模块:

// store/posts.js
export const state = () => ({
  posts: []
})

export const mutations = {
  SET_POSTS(state, posts) {
    state.posts = posts
  }
}

export const actions = {
  async fetchPosts({ commit }) {
    const posts = await this.$axios.$get('/posts')
    commit('SET_POSTS', posts)
  }
}

2. 使用存储

在组件中使用 Vuex:

<template>
  <div>
    <h1>文章列表</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex'

export default {
  computed: {
    ...mapState('posts', ['posts'])
  },
  methods: {
    ...mapActions('posts', ['fetchPosts'])
  },
  mounted() {
    this.fetchPosts()
  }
}
</script>

中间件

1. 命名中间件

创建中间件文件:

// middleware/auth.js
export default function ({ store, redirect }) {
  if (!store.state.authenticated) {
    return redirect('/login')
  }
}

2. 匿名中间件

在页面组件中定义:

<script>
export default {
  middleware({ store, redirect }) {
    if (!store.state.authenticated) {
      return redirect('/login')
    }
  }
}
</script>

3. 全局中间件

在 nuxt.config.js 中配置:

// nuxt.config.js
export default {
  router: {
    middleware: ['stats']
  }
}

插件系统

1. 创建插件

// plugins/vue-notifications.js
import Vue from 'vue'
import VueNotifications from 'vue-notifications'

Vue.use(VueNotifications)

2. 注册插件

在 nuxt.config.js 中配置:

// nuxt.config.js
export default {
  plugins: [
    '~/plugins/vue-notifications'
  ]
}

3. 客户端/服务端插件

// nuxt.config.js
export default {
  plugins: [
    { src: '~/plugins/vue-notifications', mode: 'client' }
  ]
}

布局系统

1. 默认布局

<!-- layouts/default.vue -->
<template>
  <div>
    <header>
      <nav>
        <NuxtLink to="/">首页</NuxtLink>
        <NuxtLink to="/about">关于</NuxtLink>
      </nav>
    </header>
    <main>
      <Nuxt />
    </main>
    <footer>
      <p>© 2023 My Nuxt App</p>
    </footer>
  </div>
</template>

2. 自定义布局

<!-- layouts/blog.vue -->
<template>
  <div class="blog-layout">
    <header class="blog-header">
      <h1>我的博客</h1>
    </header>
    <main class="blog-content">
      <Nuxt />
    </main>
    <aside class="blog-sidebar">
      <div class="widget">
        <h3>最新文章</h3>
        <!-- 侧边栏内容 -->
      </div>
    </aside>
  </div>
</template>

3. 使用布局

在页面组件中指定布局:

<!-- pages/about.vue -->
<template>
  <div>
    <h1>关于我们</h1>
  </div>
</template>

<script>
export default {
  layout: 'blog'
}
</script>

部署

1. 服务端渲染 (SSR)

# 构建应用
npm run build

# 启动服务
npm run start

2. 静态站点生成 (SSG)

# 生成静态文件
npm run generate

3. 单页应用 (SPA)

在 nuxt.config.js 中配置:

// nuxt.config.js
export default {
  mode: 'spa'
}

4. 部署到 Vercel

  1. 安装 Vercel CLI
npm i -g vercel
  1. 部署项目
vercel

5. 部署到 Netlify

  1. 创建 netlify.toml 文件
[build]
  command = "npm run generate"
  publish = "dist"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200
  1. 连接 GitHub 仓库并部署

最佳实践

1. 性能优化

  • 使用 nuxt-image 优化图片
  • 启用组件懒加载
  • 使用 keep-alive 缓存组件
  • 优化 CSS 和 JavaScript 打包

2. SEO 优化

  • 使用 head() 方法设置元数据
  • 实现动态 sitemap
  • 添加结构化数据
  • 优化页面加载速度

3. 代码组织

  • 使用模块化结构
  • 遵循 Vue.js 风格指南
  • 实现组件复用
  • 使用 TypeScript 增加类型安全

4. 测试

  • 单元测试 (Jest)
  • 组件测试 (Vue Test Utils)
  • E2E 测试 (Cypress)
  • 性能测试 (Lighthouse)

5. 安全

  • 防止 XSS 攻击
  • 实现 CSRF 保护
  • 使用 HTTPS
  • 安全存储敏感数据

常见问题解决

1. 路由问题

  • 检查 pages 目录结构
  • 使用 router.push() 进行编程式导航
  • 处理动态路由参数

2. 数据获取问题

  • 使用 asyncDatafetch 方法
  • 处理加载状态和错误
  • 实现数据缓存

3. 样式问题

  • 使用 CSS 模块
  • 配置 PostCSS
  • 处理全局样式

4. 构建问题

  • 优化构建配置
  • 处理依赖冲突
  • 解决内存不足问题

参考资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值