搭建nuxt3项目(框架构建)

news2024/11/16 19:56:14

需求

目标:
	我想搭建一个nuxt3的框架,实现一些基本的组件和路由、页面,方便后续遇到相关ssr项目直接复用。
同时:
	记录关于nuxt3的使用介绍

关于Nuxt(详解以及周边)

Nuxt 框架
	1、一种基于 Node.js 的服务端渲染方案 SSR(Server Side Rendering)
	支持 Vue 应用、服务器端渲染、提高页面的加载速度和 SEO
工作原理:
	1、服务端渲染:Nuxt.js 在服务器端执行 Vue 组件的渲染过程,并生成初始 HTML
	2、客户端激活:一旦初始 HTML 被发送到浏览器,Vue.js 会接管页面,并在客户端激活成一个交互式应用程序。
Nuxt 优势
SPA 和 SSR 是什么?
	1、SPA(Single Page Application)单页面应用,在客户端通过 JS 动态地构建页面。
		 优势:页面切换流畅,动态渲染变化,用户体验好,搜索引擎的支持不够友好。
		 适用企业内部项目,如管理平台。
	2、SSR(Server-Side Rendering)服务器端渲染,在服务器端生成 HTML 页面并发送给客户端。
		 优势:对搜索引擎友好,页面首次加载速度快 和 SEO,页面切换可能不够流畅(每次都是请求一个完整的 HTML 页面)
		 适用官网,对 SEO 搜索友好。
	3、Nuxt 框架
		 Nuxt 采用了混合的架构模式,可以同时支持 SSR 和 SPA。
		首次访问页面是 SSR 方式,也就是在服务器端生成 HTML 页面并发送给客户端
		后续的页面切换则使用 SPA 的方式进行,从而兼顾了 SSR 和 SPA 的优点。

场景:企业网站、商品展示 等 C 端网站,对 SEO 搜索更友好,且页面切换流畅,用户体验更好

项目搭建

1、安装项目命令和报错分析

npx nuxi init <project-name>

在这里插入图片描述

错误分析

1、安装报以上错误(其原因是大陆访问受限)
2、但是我开了代理也一样下载不下来
3、从官网issue159:原因是脚手架node程序没有走代理

错误解决方案

1、官网zip

在这里插入图片描述
2、在终端添加host代理,进行DNS域名映射

mac修改方式如下:

sudo vi /etc/hosts
输入 i 进入编辑模式,编辑完成后按 Esc后:wq 保存退出

添加
185.199.108.133 raw.githubusercontent.com

Windows修改host参考:修改本地host代理

在这里插入图片描述

运行

npm run dev
or
npm i
npm run dev

#

目录以及初始化

1、先来理解下目录

├─.nuxt              非工程代码,存放运行或发行的编译结果
├─node_modules       项目依赖
├─public             网站资源目录
├─server             接口目录
├─.gitignore         git 忽略文件
├─.npmrc             npm 配置文件
├─app.vue            根组件
├─nuxt.config.ts     nuxt 配置文件
├─package.json       项目配置文件
├─README.md          项目说明文件
└─tsconfig.json      ts 配置文件

2、nuxt 有一些约定的目录,有特殊功能,如 pages 目录的 vue 文件会自动注册路由。

├─ pages             页面目录,自动注册路由

Nuxt.js 自带路由功能,不需要额外安装和配置,无需安装 vue-router 。

├─ pages               页面目录,自动注册路由
│  └─index.vue         主页
│  └─user.vue          用户页
├─app.vue              根组件

测试一下

<template>
  <!-- 路由链接 -->
  <NuxtLink to="/">首页</NuxtLink>
  <NuxtLink to="/user">用户页</NuxtLink>
  <!-- 路由占位 -->
  <NuxtPage />
</template>
// <NuxtPage> 相当于 <RouterView>
// <NuxtLink> 相当于 <RouterLink>

在这里插入图片描述
在这里插入图片描述### SEO 优化
实现:
通过设置网页 title 和 description 等 SEO 优化信息,由服务端渲染
SEO and Meta

// 在app.vue中新增
<script setup lang="ts">
// SEO 优化
useSeoMeta({
  title: 'demo - 找工作|博客|提升',
  description:
    '求职之前,需要有经验,技术。祝愿大家找到好工作,拿到好offer。',
  author: '卡卡——程序员',
})
</script>

组件库和vw适配

安装 nuxt 版 vant-ui
npm i @vant/nuxt

nuxt.config.ts添加配置

// https://nuxt.com/docs/api/configuration/nuxt-config
// PS: 在 Nuxt 项目中,vant 组件会自动按需导入(需重启)
export default defineNuxtConfig({
  devtools: { enabled: false },
  modules: ['@vant/nuxt'],
})

index.vue测试

<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
vw 适配

安装

npm i postcss-px-to-viewport

nuxt.config.ts添加配置

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: false },
  modules: ['@vant/nuxt'],
  // 移动端适配
  postcss: {
    plugins: {
      'postcss-px-to-viewport': {
        viewportWidth: 375,
      },
    },
  },
})

页面效果px会转化为vw
在这里插入图片描述

路由配置

自动路由

在 pages 目录的 vue 文件会自动注册路由,创建以下vue文件
登录页 login.vue
注册页 register.vue
文章详情页 detail.vue
文章(TabBar)article.vue
收藏(TabBar)collect.vue
喜欢(TabBar)like.vue
我的(TabBar)user.vue

路由中间件
新建 middleware 目录,通过 Nuxt 路由中间件实现路由重定向,包括导航守卫等路由功能。

export default defineNuxtRouteMiddleware((to, from) => {
  // 首页重定向
  if (to.path === '/') {
    return navigateTo('/article')
  }
})

在这里插入图片描述

layouts 布局

目标:我们想在首页底部实现TabBar导航栏

通过 layout 实现布局的复用,新建文件 layouts/tabbar.vue

// route 开启路由模式
// to 跳转路由
<template>
  <div class="layout-page">
    <!-- 插槽 -->
    <slot />
    <!-- tabbar -->
    <van-tabbar route>
      <van-tabbar-item to="/article" icon="notes-o">面经</van-tabbar-item>
      <van-tabbar-item to="/collect" icon="star-o">收藏</van-tabbar-item>
      <van-tabbar-item to="/like" icon="like-o">喜欢</van-tabbar-item>
      <van-tabbar-item to="/user" icon="user-o">我的</van-tabbar-item>
    </van-tabbar>
  </div>
</template>

页面中使用 layout 布局
article.vue

<template>
  <NuxtLayout name="tabbar">
    <h1>文章首页</h1>
  </NuxtLayout>
</template>

为这几个路由分别配置
在这里插入图片描述
修改主题色
在 app.vue 的样式全局生效。

<style>
:root {
  --van-primary-color: #fa6d1d !important;
}
</style>

在这里插入图片描述

注册页

直接复用、一些基础vant组件使用

<template>
  <div class="register-page">
    <!-- 导航栏部分 -->
    <van-nav-bar title="用户注册" />

    <!-- 一旦form表单提交了,就会触发submit,可以在submit事件中
        根据拿到的表单提交信息,发送axios请求
    -->
    <van-form @submit="onSubmit">
      <!-- 输入框组件 -->
      <!-- \w 字母数字_   \d 数字0-9 -->
      <van-field
        v-model="form.username"
        name="username"
        label="用户名"
        placeholder="用户名"
        :rules="[
          { required: true, message: '请填写用户名' },
          { pattern: /^\w{5,}$/, message: '用户名至少包含5个字符' },
        ]"
      />
      <van-field
        v-model="form.password"
        type="password"
        name="password"
        label="密码"
        placeholder="密码"
        :rules="[
          { required: true, message: '请填写密码' },
          { pattern: /^\w{6,}$/, message: '密码至少包含6个字符' },
        ]"
      />
      <div style="margin: 16px">
        <van-button block type="primary" native-type="submit">注册</van-button>
      </div>
    </van-form>
    <NuxtLink class="link" to="/login">已注册,去登录</NuxtLink>
  </div>
</template>

<script setup lang="ts">
// 表单数据
const form = reactive({
  username: 'admin',
  password: '123456',
})

// 表单提交
const onSubmit = async () => {
  //
}
</script>

<style scoped>
.link {
  color: #069;
  font-size: 12px;
  padding-right: 20px;
  float: right;
}
</style>

请求封装axios

安装 axios,登录请求可用 axios 发送。

	npm i axios

新建 utils/request.ts 封装 axios 模块
nuxt3 utils模块
在这里插入图片描述

/* 封装axios用于发送请求 */

import axios, { AxiosResponse } from 'axios'

const service = axios.create({
  baseURL: 'http://interview-api-t.itheima.net/h5',
  timeout: 90000,
})
const request = (config: any) => {
//   if (getToken()) {
//     config.headers['csrf-token'] = getToken()
//   }
  if (config.cType) {
    config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
  }
  return config
}

const requestError = (error: any) => {
  console.error(error)
  return Promise.reject(error)
}

const response = (response: AxiosResponse) => {
  return response.data
}

const responseError = async (error: any) => {
  if (error.response.status === 403) {
    showFailToast('登录过期')
    navigateTo('/login')
    return Promise.reject(error)
  }
  if (error.response.data.code === 400) {
    showFailToast(error.response.data.message)
    return Promise.reject(error)
  }
  if (error.response.status === 500) {
    // No permission
    return Promise.reject(error)
  }
  return Promise.reject(error)
}

service.interceptors.request.use(request, requestError)
service.interceptors.response.use(response, responseError)

export default service
// register.vue 表单提交调用接口
// 表单提交
const onSubmit = async () => {
  // 注册请求
  await request({
    method: 'POST',
    url: '/user/register',
    data: form,
  })
  // 成功提示
  showSuccessToast('注册成功')
  // 跳转页面
  navigateTo('/login')
}

持久化存储 use-cookie

注意:Nuxt 服务器端不支持 localStorage 所以运行会报错,可通过 cookie 代替。
而且Nuxt支持 useCookie API存储cookie

在util中新建cookie.ts

const KEY = 'key'

// 获取
export const getToken = () => {
  return useCookie(KEY).value
}

// 设置
export const setToken = (newToken: string) => {
  useCookie(KEY, { maxAge: 60 * 60 * 24 * 14 }).value = newToken
}

// 删除
export const delToken = () => {
  useCookie(KEY).value = undefined
}

登录页逻辑

<script setup lang="ts">
// 表单数据
const form = reactive({
  username: 'admin111',
  password: '123456',
})

// 表单提交
const onSubmit = async () => {
  // 登录请求
  const res = await request({
    method:"post",
    url:'/user/login',
    data:form
  })
  // 保存 token
  setToken(res.data.token)
  // 成功提示
  showSuccessToast('登录成功')
  // 跳转页面
  navigateTo('/', {replace: true})
}
</script>

<template>
  <div class="login-page">
    <!-- 导航栏部分 -->
    <van-nav-bar title="用户登录" />

    <!-- 一旦form表单提交了,就会触发submit,可以在submit事件中
         根据拿到的表单提交信息,发送axios请求
     -->
    <van-form @submit="onSubmit">
      <!-- 输入框组件 -->
      <!-- \w 字母数字_   \d 数字0-9 -->
      <van-field
        v-model="form.username"
        name="username"
        label="用户名"
        placeholder="用户名"
        :rules="[
          { required: true, message: '请填写用户名' },
          { pattern: /^\w{5,}$/, message: '用户名至少包含5个字符' },
        ]"
      />
      <van-field
        v-model="form.password"
        type="password"
        name="password"
        label="密码"
        placeholder="密码"
        :rules="[
          { required: true, message: '请填写密码' },
          { pattern: /^\w{6,}$/, message: '密码至少包含6个字符' },
        ]"
      />
      <div style="margin: 16px">
        <van-button block type="info" native-type="submit">提交</van-button>
      </div>
    </van-form>
    <NuxtLink class="link" to="/register">注册账号</NuxtLink>
  </div>
</template>

<style scoped>
.link {
  color: #069;
  font-size: 12px;
  padding-right: 20px;
  float: right;
}
</style>

路由鉴权-导航守卫

Nuxt 有路由中间件,简化了导航守卫的实现。use-router

// middleware下的route.global.ts
// 白名单列表,记录无需权限访问的所有页面
const whiteList = ['/login', '/register']

export default defineNuxtRouteMiddleware((to, from) => {
  // 首页重定向
  if (to.path === '/') {
    return navigateTo('/article')
  }
  // 获取 token
  const token = getToken()
  if (!token && !whiteList.includes(to.path)) {
    return navigateTo('/login')
  }
})

渲染页面-封装useFetch 通过 useFetch 发送请求

为什么封装useFetch发送请求?
1、服务端先渲染静态页面,axios请求接收到数据需要客户端进行渲染页面。
2、useFetch发送的请求直接在服务端处理好,随着页面一起回来。利于seo
// 注意、函数组件都不用引入,可以直接使用,但type类型需要导入才能使用
export const useRequest = async (url: string,options?: any) => {
  const { data, error } = await useFetch(url, {
    baseURL: 'http://interview-api-t.itheima.net/h5/',
    headers: {
      Authorization: `Bearer ${getToken()}`,
    },
    ...options,
  })

  if (error.value) {
    return Promise.reject(error)
  } else {
    return data.value.data
  }
}

补充

在这里插入图片描述

其中 [id].vue  表示动态路由为detail/:id的路由

git 地址

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

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

相关文章

Java-多线程进阶

文章目录 Java多线程进阶锁的类型乐观锁vs悲观锁读写锁重量级锁vs轻量级锁自旋锁公平锁vs非公平锁可重入锁vs不可重入锁 CASCAS介绍和原理CAS应用自旋锁CAS 的 ABA 问题 Synchronized 原理Callable 接口JUC常见类ReentrantLock原子类线程池信号量 SemaphoreCountDownLatch 线程…

Unity之ShaderGraph如何实现旋涡效果

前言 今天我们来通过ShaderGraph来实现一个旋涡的效果 如下图所示&#xff1a; 主要节点 Distance&#xff1a;返回输入 A 和输入 B 的值之间的欧几里德距离。除了其他方面的用途&#xff0c;这对于计算空间中两点之间的距离很有用&#xff0c;通常用于计算有符号距离函数 (…

JAVA基础(JAVA SE)学习笔记(八)面向对象编程(高级)

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 第二阶段&#xff1a;Java面向对象编程 6.面向对象编程&#xff08;基础&#xff09; 7.面向对象编程&…

C++标准模板(STL)- 类型支持 (类型特性,is_void,is_null_pointer,is_integral)

类型特性 类型特性定义一个编译时基于模板的结构&#xff0c;以查询或修改类型的属性。 试图特化定义于 <type_traits> 头文件的模板导致未定义行为&#xff0c;除了 std::common_type 可依照其所描述特化。 定义于<type_traits>头文件的模板可以用不完整类型实…

【小呆的概率论学习笔记】抽样调查之用抽样样本估计母体数字特征

文章目录 1. 随机变量的数字特征1.1 随机变量的均值&#xff08;期望&#xff09;1.2 随机变量的方差1.3 随机变量的协方差 2. 抽样调查3. 用抽样样本估计母体数字特征3.1 估计母体样本均值3.2 抽样样本均值的方差3.2 估计母体样本方差 1. 随机变量的数字特征 随机变量本质上是…

手把手教你在项目中引入Excel报表组件

摘要&#xff1a;本文由葡萄城技术团队原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 GrapeCity Documents for Excel&#xff08;以下简称GcExcel&#xff09;是葡萄城公司的…

《VS2013+ Qt5.6 创建Qt对话框(*.ui 文件, *.h, *.cpp )》

标题&#xff1a;如何在Visual Studio 2013中创建Qt对话框项目 简介 在本篇博客中&#xff0c;我们将介绍如何使用Visual Studio 2013和Qt 5.6创建一个Qt对话框项目&#xff0c;包括创建.ui文件、.h文件和.cpp文件&#xff0c;以及构建一个基本的用户界面和业务逻辑。&#x…

自建的离散傅里叶变换matlab程序实现及其与matlab自带函数比较举例

自建的离散傅里叶变换matlab程序实现及其与matlab自带函数比较举例 在matlab中有自带的离散傅里叶变换程序&#xff0c;即fft程序&#xff0c;但该程序是封装的&#xff0c;无法看到源码。为了比较清楚的了解matlab自带的实现过程&#xff0c;本文通过自建程序实现matlab程序&…

DenseNet 和 FractalNet学习笔记

文章目录 网络结构模型细节下采样增长率 代码实现FractalNet 模型(2016) 网络结构 假设输入为一个图片X0&#xff0c;经过一个L层的神经网络&#xff0c;第l层的特征输出记作Xl&#xff0c;那么残差连接的公式如下所示&#xff1a; x l H l ( X l − 1 ) X l − 1 x_lH_l(X…

【光电子技术+光纤通信】博资考

光电子技术与光纤通信基础总结 几何光学波动光学光电子器件激光器光调制器光探测器光纤 几何光学 折射率是比值定义式&#xff0c;定义为入射介质光速比上折射介质光速&#xff0c;它与optical density意义相似&#xff0c;可以表示传播介质对于光传播的阻碍程度&#xff0c;因…

Postman的简单使用

Postman简介 官网 Postman是Google公司开发的一款功能强大的网页调试与发送HTTP请求&#xff0c;并能运行测试用例的Chrome插件 使用Postman进行简单接口测试 新建测试 → 选择请求方式 → 请求URL&#xff0c;下面用百度作为例子&#xff1a; 参考文档 [1] Postman使用教程…

AIR101 LuatOS LVGL 显示多个标签例程

屏幕资料 AIR101与屏幕连接 PC端仿真环境合宙官方PC端版本环境搭建教程 PC电脑仿真 -- sys库是标配 _G.sys require("sys") sys.taskInit(function()local cnt0lvgl.init(480,320)--lvgl初始化local cont lvgl.cont_create(nil, nil);-- lvgl.cont_set_fit(cont, …

cocosCreator 之 dispatchEvent事件分发

版本&#xff1a; 3.8.0 语言&#xff1a; TypeScript 环境&#xff1a; Mac Node事件派发 cocosCreator支持使用Node节点进行事件派发(dispatchEvent)&#xff0c;事件派发系统是按照 Web 的事件冒泡及捕获标准 实现的。 事件派发主要通过冒泡的方式逐渐向父节点传递。 在派…

整数智能·迪拜GITEX 2023 |探索未来科技,感受创新脉搏

第43届GITEX GLOBAL在迪拜世界贸易中心盛大开幕&#xff0c;聚集来自全球各地的6000多家参展企业&#xff0c;包含大量来自于人工智能、区块链、网络安全、可持续技术等领域的科技巨头和革命性初创企业&#xff0c;展示全球科技最新趋势和创新机遇。GITEX GLOBAL始办于1981年&a…

OpenText 安全取证软件——降低成本和风险的同时,简化电子取证流程

OpenText 安全取证软件&#xff0c;行业标准的数字调查解决方案&#xff0c;适用于各种规模和各种行业的组织 降低成本和复杂性 • 远程调查比轮流调查过程更有效 对结果持有信心 • 磁盘级可见性可以完成相关端点数据的搜索和收集 谨慎调查 • 完整的网络调查&#xf…

Linux常用文件和目录管理

本文旨在对y总的Linux基础课做学习记录&#xff0c;方便日后复习 参考视频&#xff1a;Linux基础课 参考教程&#xff1a;Linux教程 0 绝对路径和相对路径 Linux 的目录结构为树状结构 绝对路径&#xff1a;由根目录 / 写起&#xff0c;例如&#xff1a; /usr/share/doc相对…

华为云2023年双十一服务器优惠价格表及活动大全

2023华为云双11优惠活动「云上优选 特惠来袭」&#xff0c;阿腾云atengyun.com整理云服务器优惠价格表&#xff0c;华为云L实例-2核2G3M一年优惠价89元、L实例-2核2G4M价格108元一年、L实例-2核4G5M优惠价198元一年&#xff0c;三年1000元、HECS云服务器-1核2G1M带宽39元一年、…

【C++】继承和多态

继承和多态 一、继承1. 继承概念2. 继承定义&#xff08;1&#xff09;继承的格式定义&#xff08;2&#xff09;继承父类成员访问方式的变化 3. 父类和子类对象赋值转换4. 继承中的作用域5. 子类的默认成员函数6. 继承与友元7. 继承与静态成员8. 复杂的菱形继承及菱形虚拟继承…

Zynq UltraScale+ XCZU9EG 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优越性4、详细设计方案设计原理框图IMX214 摄像头及其配置D-PHY 模块CSI-2-RX 模块Bayer转RGB模块伽马矫正模块VDMA图像缓存Video Scaler 图像缓存DP 输出 5、vivado工程详解PL端FPGA硬件设计…

linux安装nginx 1.25.2

1.下载nginx-1.25.2.tar.gz放在/opt下 wget http://nginx.org/download/nginx-1.25.2.tar.gz 2.解包 Nginx 软件包&#xff1a; tar -xvf nginx-1.25.2.tar.gz 3.安装 Nginx 依赖&#xff1a; 在安装 Nginx 之前&#xff0c;需要先安装一些依赖库&#xff1a;pcre、openss…