nuxt3:我们开始吧!
创始人
2024-02-24 23:23:29
0

一、背景介绍

2022 年 11 月 16 日,全球最大的 Nuxt 会议 Nuxt Nation 2022 在线举行,并正式发布了 Nuxt.js 3.0 的第一个稳定版本。Nuxt 3 是基于 ViteVue3 和 Nitro 的 Nuxt 框架的现代重写,具有一流的 Typescript 支持,是两年多研究、社区反馈、创新和实验的结果。为每个人提供了一个愉快的 Vue 全栈开发体验。

因为nuxt优越的服务端渲染能力,所以对于nuxt3项目关注已久!我们开始吧!

二、官方网址

Nuxt 3 - 中文文档

Nuxt - The Intuitive Vue Framework

Announcing 3.0 · Nuxt

Nuxt - Installation

https://github.com/nuxt/create-nuxt-app/blob/master/README.md

三、新特性介绍

1、更轻量:以现代浏览器为目标的服务器部署和客户端产物最多可缩小 75 倍
2、更快:基于 nitro 提供动态代码分割能力,以优化冷启动性能
3、Hybrid:增量静态生成和其他的高级功能现在都成为可能
4、Suspense:在任意组件和导航前后都可以获取数据
5、Composition API:使用 Composition API 和 Nuxt 3 的 composables 实现真正的代码复用
6、Nuxt CLI:没有任何依赖,帮你轻松搭建项目和集成模块
7、Nuxt Devtools:通过直接在浏览器中查看信息和快速修复实现更快地工作
8、Nuxt Kit:具有 Typescript 和跨版本兼容性的全新模块开发
9、Webpack 5:更快的构建时间和更小的包大小,无需配置
10、Vite:使用 Vite 作为打包工具,体验闪电般快速的 HMR
11、Vue 3:Vue 3 是你下一个 Web 应用程序的坚实基础
12、TypeScript:使用原生 TypeScript 和 ESM 构建,无需额外步骤

Nuxt 3.0 稳定版正式发布,基于 Vue 3 的 Web 框架

四、重要概念

SPA应用:也就是单页应用,这些多是在客户端的应用,不能进行SEO优化(搜索引擎优化)。

SSR应用:在服务端进行渲染,渲染完成后返回给客户端,每个页面有独立的URL,对SEO友好。

约定式路由:不需要配置路由,在根目录pages目录下创建业务页面,即可访问。

约定式配置:如layouts布局、middleware、plugins

五、启动基础项目

https://github.com/nuxt/create-nuxt-app/blob/master/README.md

5.1、创建项目:

创建nuxt3项目:

pnpm dlx nuxi init nuxt-app

 npx nuxi init nuxt3-app

5.2、安装依赖

pnpm install --shamefully-hoist

5.3、启动项目

启动成功

六、项目配置、基础使用

6.1、访问pages/index.vue

根目录app.vue,替换为:


pages/index.vue

pages/about.vue  

这样就可以访问页面了:

6.2、动态路由

6.2.1、目录结构

6.2.2、访问:/user

如果没有pages/user/index页面,只有[id].vue,访问的时候式404页面

6.2.3、访问:/user/1,动态路由,获取动态路由参数

{{$route.params.id}}

6.2.4、访问:/user/1?name=snow,动态路由,获取路由普通参数:

{{$route.query.name}}

 6.2.5、通过useRoute()获取路由信息

const route = useRoute()

6.3、路由跳转

经过测试一下几种方式均成功跳转。页面内容均正常展示。

6.3.1、

user-id

6.3.2、 

user-id-2

6.3.3、

user-id-3

6.3.4、编程式路由

6.4、加载静态资源

 nuxt项目tsconfig.json有配置,public目录下的文件可以省略/public目录,我这里测试不可以,后续会再研究

6.5、设置页面title,不会在页面展示,只会在页面title部分展示

6.5.1、

snow-title

如图:

 ctrl + u:

 6.5.2、使用useHead()方法

useHead({title: 'snow-title-2'
})

设置成功,useHead优先级小于标签。</p> <p>6.5.3、同理使用useHead设置页面的TDK信息</p> <pre><code><script setup lang="ts"> useHead({title: 'snow-title-2',meta: [{ name: 'description', content: 'snow-desc'},{ name: 'keywords', content: 'snow-kw'}] }) </script></code></pre> <p><img alt="" height="227" src="https://img.pic99.top/dingtaihe/202402/21bf5242f476340.png" width="977" /></p> <p></p> <p><strong>6.6、layouts</strong></p> <p>6.6.1、理解:布局、页面布局、公共布局、基础布局</p> <p>6.6.2、根目录创建layouts目录,/layouts/default.vue</p> <pre><code><template><div>snow-default-layout</div><slot /> </template><script setup lang="ts"></script><style scoped></style> </code></pre> <p>6.6.3、app.vue</p> <pre><code><template><NuxtLayout><NuxtPage/></NuxtLayout><!-- <div><NuxtWelcome /></div> --> </template> </code></pre> <p><img alt="" height="533" src="https://img.pic99.top/dingtaihe/202402/820e5648f741e3b.png" width="991" /></p> <p> 6.6.4、</p> <p><img alt="" height="265" src="https://img.pic99.top/dingtaihe/202402/9b9a6e79f5fb1ff.png" width="648" /></p> <p> 6.6.5、某页面不想使用layout:</p> <pre><code>definePageMeta({layout: false })</code></pre> <p>6.6.6、某页面使用指定layout</p> <p><img alt="" height="151" src="https://img.pic99.top/dingtaihe/202402/f4a71e60a12ab02.png" width="345" /></p> <pre><code>definePageMeta({layout: 'layout-snow' })</code></pre> <p>  6.6.7、动态设置layout</p> <pre><code>const router = useRoute() function enableLayout () {router.meta.layout = "layout-snow" }</code></pre> <p>6.6.8、全局设置,指定layout</p> <pre><code class="hljs"><template><NuxtLayout :name="layoutSnow"><NuxtPage/></NuxtLayout><!-- <div><NuxtWelcome /></div> --> </template> <script setup lang="ts"> const layoutSnow = ref("layout-snow") </script></code></pre> <p><strong>6.7、plugins</strong></p> <p>/plugins/index.ts</p> <pre><code class="hljs">export default defineNuxtPlugin(()=>{return {provide: {hello: (msg: string) => `hello ${msg}`}} })</code></pre> <p>/pages/plugin.vue</p> <pre><code class="hljs"><template><div>snow-plugin</div> </template><script setup lang="ts"> const { $hello } = useNuxtApp() console.log('9', $hello('world')) </script><style scoped> </style> </code></pre> <p><img alt="" height="505" src="https://img.pic99.top/dingtaihe/202402/e4223fe8f927.png" width="958" /></p> <p><strong>6.8、middleware</strong></p> <p>/middleware/auth.ts</p> <pre><code class="hljs">export default defineNuxtRouteMiddleware((to, from)=>{console.log("auth") }) </code></pre> <p>/middleware/snow.ts</p> <pre><code class="hljs">export default defineNuxtRouteMiddleware((to, from)=>{console.log("snow") }) </code></pre> <p>/pages/plugin.vue</p> <pre><code class="hljs"><template><div>snow-plugin</div> </template><script setup lang="ts">definePageMeta({middleware: ["auth", "snow"] })</script><style scoped> </style> </code></pre> <p> 如图:</p> <p><img alt="" height="544" src="https://img.pic99.top/dingtaihe/202402/7a573f582af71e8.png" width="910" /></p> <p>6.9、封装接口请求</p> <p>待补充</p> <p>6.10、多环境开发</p> <p>待补充</p> <p>6.11、其他内容</p> <p>待补充</p> <p><strong>七、过程记录</strong></p> <p>7.1、init项目不成功</p> <p><img alt="" height="229" src="https://img.pic99.top/dingtaihe/202402/420ff4adf08c9bb.png" width="759" />解:墙内的同学可能创建不成功,这里推荐一个链接:https://github.com/nuxt/starter</p> <p>7.2、useHead接收参数如下:</p> <pre><code>useHead(meta: Computable<MetaObject>): voidinterface MetaObject extends Record<string, any> {charset?: stringviewport?: stringmeta?: Array<Record<string, any>>link?: Array<Record<string, any>>style?: Array<Record<string, any>>script?: Array<Record<string, any>>noscript?: Array<Record<string, any>>titleTemplate?: string | ((title: string) => string)title?: stringbodyAttrs?: Record<string, any>htmlAttrs?: Record<string, any> }</code></pre> <pre><code>charset: 指定 HTML 的字元编码,预设为 utf-8。 viewport: 设定网页的可见区域,预设为 width=device-width, initial-scale=1。 meta: 接受一个阵列,阵列中的每个元素,都將会建立一个 <meta> 标记,元素中物件的属性将对应至的属性。 link: 接受一个阵列,阵列中的每个元素,都将会建立一个 <link> 标记,元素中物件的属性将对应至的属性。 style: 接受一个阵列,阵列中的每個元素,都将会建立一个 <style> 标记,元素中物件的属性将对应至的属性。 script: 接受一个阵列,阵列中的每個元素,都将会建立一个 <script> 标记,元素中物件的属性将对应至的属性。 noscript: 接受一个阵列,阵列中的每個元素,都将会建立一个 <noscript> 标记,元素中物件的属性将对应至的属性。 titleTemplage: 接受一個字串或函數,用來动态的设定该页面元件的网页标题。 title: 在页面元件设置静态的网页标题。 bodyAttrs: 接受一个物件,设置网页中标识的属性,物件中的属性将对应至的属性。 htmlAttrs: 接受一个物件,设置网页中标识的属性,物件中的属性将对应至的属性。</code></pre> <p>理解useHead:相当于设置页面<head>标签内相关内容。</p> <p></p> <p><strong>八、欢迎交流指正,关注我,一起学习。</strong></p> <p><img alt="" height="425" src="https://img.pic99.top/dingtaihe/202402/bb9a339fe9eea80.png" width="859" /></p> <p> </p> <p><strong>参考链接:</strong></p> <p>[Day 24] Nuxt 3 搜尋引擎最佳化 (SEO) 與 HTML Meta Tag - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天</p> <p>Nuxt3-动态更改meta信息(关键词、标题、描述)_fat_shady的博客-CSDN博客</p> <p>令人愉快的 Nuxt3 教程 (一): 应用的创建与配置 - 知乎</p> <p>技术胖-Nuxt3从零到实战手把手 免费视频图文教程</p> <p>Nuxt.js 3.0 正式发布! - 知乎</p> <p></p> <!--end::Text--> </div> <!--end::Description--> <div class="mt-5"> <!--关键词搜索--> </div> <div class="mt-5"> <p class="fc-show-prev-next"> <strong>上一篇:</strong><a href="/news/36968.html">[附源码]Python计算机毕业设计Django+Vue的健身房会员系统的设计与实现</a><br> </p> <p class="fc-show-prev-next"> <strong>下一篇:</strong><a href="/news/36970.html">网页JS自动化脚本(二)查找定位页面元素的方法</a> </p> </div> <!--begin::Block--> <div class="d-flex flex-stack mb-2 mt-10"> <!--begin::Title--> <h3 class="text-dark fs-5 fw-bold text-gray-800">相关内容</h3> <!--end::Title--> </div> <div class="separator separator-dashed mb-9"></div> <!--end::Block--> <div class="row g-10"> </div> </div> <!--end::Table widget 14--> </div> <!--end::Col--> <!--begin::Col--> <div class="col-xl-4 mt-0"> <!--begin::Chart Widget 35--> <div class="card card-flush h-md-100"> <!--begin::Header--> <div class="card-header pt-5 "> <!--begin::Title--> <h3 class="card-title align-items-start flex-column"> <!--begin::Statistics--> <div class="d-flex align-items-center mb-2"> <!--begin::Currency--> <span class="fs-5 fw-bold text-gray-800 ">热门资讯</span> <!--end::Currency--> </div> <!--end::Statistics--> </h3> <!--end::Title--> </div> <!--end::Header--> <!--begin::Body--> <div class="card-body pt-3"> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144772.html" class="text-dark fw-bold text-hover-primary fs-6">AI辅助法律普及:个性化法律知...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">AI辅助法律普及:法律知识个性化推送与法律文书自动生成,共创法治美景 随着科技的飞速发展,人工智能(...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144771.html" class="text-dark fw-bold text-hover-primary fs-6">沈阳劳动纠纷律师推荐辽宁华颖律...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">在劳动争议日益增多的当下,劳动者与用人单位之间的权益纠纷往往涉及工资、社保、工伤、劳动关系确认等诸多...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144768.html" class="text-dark fw-bold text-hover-primary fs-6">上海发布“游戏沪十条”,为游戏...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">12月19日,2025年度中国游戏产业年会在上海徐汇西岸国际会展中心落幕。大会发布《2025年中国游...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144769.html" class="text-dark fw-bold text-hover-primary fs-6">原创 1...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">山有信/文 近日,“腾讯起诉拼多多不正当竞争”引发了媒体关注和网友热议,反做空一线通过查询案沪通发现...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144766.html" class="text-dark fw-bold text-hover-primary fs-6">皇氏集团的“冰与火”:股价涨停...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">水牛奶龙头皇氏集团(002329.SZ)近日颇受资金追捧,本周五个交易日收获3个涨停。然而股价大涨难...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144765.html" class="text-dark fw-bold text-hover-primary fs-6">深化药械改革 重庆“政策陪跑”...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">央广网重庆12月21日消息(记者白刁尹)近日,重庆市药品监督管理局召开“深化药械改革——重庆在行动”...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144767.html" class="text-dark fw-bold text-hover-primary fs-6">原创 大...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">12月18日晚上,有人在微博看到汪小菲凌晨发帖,指着抖音副总裁李亮说平台封他账号不合理,还附了他和前...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144764.html" class="text-dark fw-bold text-hover-primary fs-6">推荐靠谱境外投资咨询律师,杨国...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">在当今全球化的经济浪潮中,越来越多的企业和高净值人群将目光投向了境外投资领域。然而,境外投资涉及到复...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144761.html" class="text-dark fw-bold text-hover-primary fs-6">创新政策吸引高附加值企业集聚海...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">随着高附加值产品的发展,相关产业也将实现升级,从而提高整个经济的发展质量和效益。当外贸、医疗、粮油和...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/news/144763.html" class="text-dark fw-bold text-hover-primary fs-6">2025年平潭刑事律师专业律师...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">刑事案件的处理直接关系到当事人的自由、财产乃至生命权益,其专业性、对抗性与程序复杂性对辩护律师提出了...</span> </div> <!--end::Title--> </div> </div> <!--end::Body--> </div> <!--end::Chart Widget 35--> </div> <!--end::Col--> </div> </div> <!--end::Content container--> </div> <!--end::Content--> </div> <!--end::Content wrapper--> <!--begin::Footer--> <div id="kt_app_footer" class="app-footer"> <!--begin::Footer container--> <div class="app-container container-xxl d-flex flex-column flex-md-row flex-center flex-md-stack py-3"> <!--begin::Copyright--> <div class="text-dark order-2 order-md-1"> <span class="text-muted fw-semibold me-1">2025 ©</span> <a href="/" target="_blank" class="text-gray-800 text-hover-primary">鼎泰网</a> </div> <!--end::Copyright--> <!--begin::Menu--> <ul class="menu menu-gray-600 menu-hover-primary fw-semibold order-1"> <li class="menu-item"> <a href="/news/" target="_blank" class="menu-link px-2">资讯</a> </li> <li class="menu-item"> <a href="/caijing/" target="_blank" class="menu-link px-2">财经</a> </li> </ul> <!--end::Menu--> </div> <!--end::Footer container--> </div> <!--end::Footer--> </div> <!--end:::Main--> </div> <!--end::Wrapper--> </div> <!--end::Page--> </div> <!--end::App--> <div id="kt_scrolltop" class="scrolltop" data-kt-scrolltop="true"> <!--begin::Svg Icon | path: icons/duotune/arrows/arr066.svg--> <span class="svg-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect opacity="0.5" x="13" y="6" width="13" height="2" rx="1" transform="rotate(90 13 6)" fill="currentColor"></rect> <path d="M12.5657 8.56569L16.75 12.75C17.1642 13.1642 17.8358 13.1642 18.25 12.75C18.6642 12.3358 18.6642 11.6642 18.25 11.25L12.7071 5.70711C12.3166 5.31658 11.6834 5.31658 11.2929 5.70711L5.75 11.25C5.33579 11.6642 5.33579 12.3358 5.75 12.75C6.16421 13.1642 6.83579 13.1642 7.25 12.75L11.4343 8.56569C11.7467 8.25327 12.2533 8.25327 12.5657 8.56569Z" fill="currentColor"></path> </svg> </span> <!--end::Svg Icon--> </div> <!--begin::Javascript--> <script>var hostUrl = "/static/default/pc/";</script> <!--begin::Global Javascript Bundle(mandatory for all pages)--> <script src="/static/default/pc/plugins/global/plugins.bundle.js"></script> <script src="/static/default/pc/js/scripts.bundle.js"></script> <!--end::Global Javascript Bundle--> <!--end::Javascript--> </body> <!--end::Body--> </html>