You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"use client";// Error boundaries must be Client ComponentsexportdefaultfunctionGlobalError({ error, reset }: {error: Error&{digest?: string};reset: ()=>void}){return(// global-error must include html and body tags<html><body><h2>Something went wrong!</h2><buttononClick={()=>reset()}>Try again</button></body></html>);}
app/not-found.tsx 路由未找到 UI
importLinkfrom"next/link";exportdefaultfunctionNotFound(){return(<div><h2>Not Found</h2><p>Could not find requested resource</p><Linkhref="/">Return Home</Link></div>);}
Nuxt.js
v2
layouts/error.vue
<template><divclass="container"><h1v-if="error.statusCode === 404">Page not found</h1><h1v-else>An error occurred</h1><nuxt-linkto="/">Home page</nuxt-link></div></template><script>exportdefault{props: ["error"],layout: "blog",// you can set a custom layout for the error page};</script>
<template><h1>{{ title }}</h1></template><script>exportdefault{data(){return{title: "Hello World!",};},head(){return{title: this.title,meta: [// To avoid duplicated meta tags when used in child component, set up an unique identifier with the hid key{hid: "description",name: "description",content: "My custom description",},],};},};</script>
<scriptsetuplang="ts">useHead({title: "My App",meta: [{name: "description",content: "My amazing site."}],bodyAttrs: {class: "test",},script: [{innerHTML: "console.log('Hello world')"}],});useSeoMeta({title: "My Amazing Site",ogTitle: "My Amazing Site",description: "This is my amazing site, let me tell you all about it.",ogDescription: "This is my amazing site, let me tell you all about it.",ogImage: "https://example.com/image.png",twitterCard: "summary_large_image",});</script>
Assets
Next.js
public
/*|- public/|-- my-image.png*/importImagefrom"next/image";// https://nextjs.org/docs/app/api-reference/components/imageexportdefaultfunctionmyImage(){return(<Imagesrc="/my-image.png"alt="Picture of the author"// width={500} automatically provided// height={500} automatically provided// blurDataURL="data:..." automatically provided// placeholder="blur" // Optional blur-up while loading/>);}
assets
/*|- assets/|-- images/|-----open-source.png*/importImagefrom"next/image";// https://nextjs.org/docs/app/api-reference/components/imageimportopenSourcefrom"/assets/images/open-source.png";exportdefaultfunctionmyImage(){return(<Imagesrc={openSource}alt="Picture of the author"// width={500} automatically provided// height={500} automatically provided// blurDataURL="data:..." automatically provided// placeholder="blur" // Optional blur-up while loading/>);}
Nuxt.js
assets
By default, Nuxt uses vue-loader, file-loader and url-loader for strong assets serving.
// components/ExampleDialog.jsimport{useState}from"react";import{Dialog}from"@reach/dialog";importVisuallyHiddenfrom"@reach/visually-hidden";import"@reach/dialog/styles.css";functionExampleDialog(props){const[showDialog,setShowDialog]=useState(false);constopen=()=>setShowDialog(true);constclose=()=>setShowDialog(false);return(<div><buttononClick={open}>Open Dialog</button><DialogisOpen={showDialog}onDismiss={close}><buttonclassName="close-button"onClick={close}><VisuallyHidden>Close</VisuallyHidden><spanaria-hidden>×</span></button><p>Hello there. I am a dialog</p></Dialog></div>);}
exportdefault{css: [// Load a Node.js module directly (here it's a Sass file)"bulma",// CSS file in the project"~/assets/css/main.css",// SCSS file in the project"~/assets/css/main.scss",],};
v3
全局样式
<!-- pages/index.vue-->
<script>
// Use a static import for server-side compatibility
import "~/assets/css/first.css";
// Caution: Dynamic imports are not server-side compatible
import("~/assets/css/first.css");
</script>
<style lang="scss">
@use "~/assets/scss/main.scss";
</style>
// posts will be populated at build time by getStaticProps()functionBlog({ posts }){return(<ul>{posts.map((post)=>(<li>{post.title}</li>))}</ul>);}// This function gets called at build time on server-side.// It won't be called on client-side, so you can even do// direct database queries. See the "Technical details" section.exportasyncfunctiongetStaticProps(){// Call an external API endpoint to get posts.// You can use any data fetching libraryconstres=awaitfetch("https://.../posts");constposts=awaitres.json();// By returning { props: { posts } }, the Blog component// will receive `posts` as a prop at build timereturn{props: {
posts,},};}exportdefaultBlog;
functionPage({ data }){// Render data...}exportasyncfunctiongetServerSideProps(){constres=awaitfetch(`https://.../data`);constdata=awaitres.json();return{props: { data }};}exportdefaultPage;
Nuxt.js
v2
<template><divv-if="$fetchState.error">Something went wrong 😭</div><divv-if="$fetchState.pending">Loading...</div><divv-else><h1>{{ post.title }}</h1><pre>{{ post.body }}</pre><button@click="$fetch">Refresh</button></div></template><script>importfetchfrom"node-fetch";exportdefault{data(){return{post: {},};},asyncfetch(){this.post=awaitthis.$http.$get("xxx");},fetchOnServer: true,};</script>
v3
客户端请求
$fetch 用户纯客户端渲染, 在 SSR 期间,数据会被获取两次,一次在服务器上,一次在客户端上。
<scriptsetuplang="ts">const{ data }=awaituseFetch("/api/data");asyncfunctionhandleFormSubmit(){constres=await$fetch("/api/submit",{method: "POST",body: {// My form data},});}</script><template><divv-if="data == null">No data</div><divv-else><form@submit="handleFormSubmit"><!-- form input tags --></form></div></template>
functionPage({ data }){// Render data...}exportasyncfunctiongetStaticProps(context){constres=awaitfetch(`https://.../data`);constdata=awaitres.json();if(!data){return{notFound: true,};}return{props: { data },// will be passed to the page component as props};}
getStaticProps 只能从页面导出。您无法从非页面文件导出它。
Nuxt.js
v2
nuxt.config.js
exportdefault{/* ** Plugins to load before mounting the App */plugins: [{src: "~/plugins/plugin/main.js",ssr: true,},],};
plugin/main.js
exportdefault({ app, store },inject)=>{// Inject $hello(msg) in Vue, context and store.inject("hello",(msg)=>console.log(`Hello ${msg}!`));// vuex缓存!isServer()&&createPersistedState({key: `vuex_store`,storage: window.sessionStorage,})(store);};
默认情况下存在的所有上下文:
function(context){// Could be asyncData, nuxtServerInit, ...// Always availableconst{
app,
store,
route,
params,
query,
env,
isDev,
isHMR,
redirect,
error,
$config
}=context// Only available on the Server-sideif(process.server){const{ req, res, beforeNuxtRender, beforeSerialize }=context}// Only available on the Client-sideif(process.client){const{ from, nuxtState }=context}}
pages/index.vue
exportdefault{mounted(){this.$hello("mounted");// will console.log 'Hello mounted!'},asyncData(context){// Universal keysconst{ app, store, route, params, query, env, isDev, isHMR, redirect, error, $hello }=context;// Server-sideif(process.server){const{ req, res, beforeNuxtRender }=context;}// Client-sideif(process.client){const{ from, nuxtState }=context;}$hello("asyncData");// If using Nuxt <= 2.12, use 👇app.$hello("asyncData");return{project: "nuxt"};},};
<!--app.vue --><scriptsetuplang="ts">constnuxtApp=useNuxtApp();nuxtApp.provide("hello",(name)=>`Hello ${name}!`);console.log(nuxtApp.$hello("name"));// Prints "Hello name!"</script>
// https://nuxt.com/docs/guide/going-further/internals#the-nuxtapp-interfaceconstnuxtApp={
vueApp,// the global Vue application: https://vuejs.org/api/application.html#application-api
versions,// an object containing Nuxt and Vue versions// These let you call and add runtime NuxtApp hooks// https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/nuxt.ts#L18
hooks,
hook,
callHook,// Only accessible on server-sidessrContext: {
url,
req,
res,
runtimeConfig,
noSSR,},// This will be stringified and passed from server to clientpayload: {serverRendered: true,data: {},state: {}}provide: (name: string,value: any)=>void}
// nuxt.config.tsexportdefaultdefineNuxtConfig({runtimeConfig: {// The private keys which are only available within server-sideapiSecret: "123",// Keys within public, will be also exposed to the client-sidepublic: {apiBase: "/api",},},});
Basic-Routes
Next.js
Nuxt.js
Dynamic-Routes
Next.js
Nuxt.js
Link
Next.js
Nuxt.js
Layout
Next.js
./pages/_app.js
: automatically apply to all pagesNuxt.js
v2
layouts/with-header-footer.vue
: create layoutpages/index.vue
: apply layoutv3
layout/default.vue
~/app.vue
Error-Page
Next.js
app/global-error.tsx
意外运行错误 UIapp/not-found.tsx
路由未找到 UINuxt.js
v2
layouts/error.vue
v3
通过在应用程序的源目录中添加
~/error.vue
(与app.vue
并排)来自定义默认错误页面。Meta-Tag
Next.js
Nuxt.js
v2
nuxt.config.js
~/app.html
v3
全局默认
页面维度
可以使用 useHead 或 useSeoMeta 钩子 自定义:
Assets
Next.js
public
assets
Nuxt.js
assets
By default, Nuxt uses vue-loader, file-loader and url-loader for strong assets serving.
在 css 文件中,如果需要引用 assets 目录,请使用
~assets/your_image.png
(不带斜杠)处理动态图像时,您需要使用 require
static
automatically served
CSS
Next.js
全局样式
在
pages/_app.js
文件中导入(import)CSS 文件。首先创建一个
pages/_app.js
文件(如果不存在的话)。 然后import
该styles.css
文件。这些样式 (
styles.css
) 将应用于你的应用程序中的所有页面和组件。 由于样式表的全局特性,并且为了避免冲突,你应该 只在pages/_app.js
文件中导入(import)样式表。从 node_modules 目录导入(import)样式
对于全局样式表(例如 bootstrap 或 nprogress),你应该在
pages/\_app.js
文件中对齐进行导入(import)。对于导入第三方组件所需的 CSS,可以在组件中进行。
组件级 CSS
Next.js 通过
[name].module.css
文件命名约定来支持 CSS 模块 。CSS 模块通过自动创建唯一的类名从而将 CSS 限定在局部范围内。 这使您可以在不同文件中使用相同的 CSS 类名,而不必担心冲突。
此行为使 CSS 模块成为包含组件级 CSS 的理想方法。 CSS 模块文件 可以导入(import)到应用程序中的任何位置。
例如,假设
components/
目录下有一个可重用Button
组件:首先,创建
components/Button.module.css
文件并填入以下内容:然后,创建
components/Button.js
文件,导入(import)并使用上述 CSS 文件:Nuxt.js
v2
全局设置 CSS 文件/模块/库(包含在每个页面中)
v3
全局样式
组件级别 CSS
Fetch-On-Server
Next.js
getInitialProps can only be used in the default export of every page
>= v9.3
SWR
推荐的客户端请求 React Hook:
getStaticProps
Next.js 将在构建时使用 getStaticProps 返回的 props 预渲染此页面 (SSG 静态渲染)
getServerSideProps
Next.js 将使用 getServerSideProps 返回的数据在每个请求上预渲染此页面。(SSR 服务端渲染)
Nuxt.js
v2
v3
客户端请求
$fetch 用户纯客户端渲染, 在 SSR 期间,数据会被获取两次,一次在服务器上,一次在客户端上。
服务端渲染
useFetch 和 useAsyncData 组合函数用于服务端和客户端同构的环境。
State-Management
Next.js
TODO:
Nuxt.js
v2
Nuxt2 使用 fetch 方法获取数据,存储在
store
中。store/website.js
pages/index.vue
v3
Nuxt 提供强大的状态管理库和
useState
组合式 API,用于创建响应式且支持服务器端渲染的共享状态。useState 是一个支持服务器端渲染的 ref 替代方案。它的值将在服务器端渲染后(客户端水合期间)保留,并通过唯一的键在所有组件之间共享。
我们利用 Pinia 模块 创建全局存储并在整个应用程序中使用它。
stores/website.ts
app.vue
Context
Next.js
如果你导出从页面 async 调用的函数 getStaticProps,Next.js 将在构建时使用返回的 props 预渲染此页面 getStaticProps。
该 context 参数是一个包含以下键的对象:
getStaticProps 应返回一个具有以下内容的对象:
Nuxt.js
v2
nuxt.config.js
plugin/main.js
默认情况下存在的所有上下文:
pages/index.vue
v3
useNuxtApp 访问 Nuxt 应用程序的共享运行时上下文。
Source Map
Next.js
Nuxt.js
v2
v3
Environment Variables
Next.js
以
env.$(NODE_ENV)
来加载环境变量,NODE_ENV
允许有以下几种值。自动加载
Js 内置支持将环境变量从
. env*
文件加载到process.env
中手动加载
具体使用:
Nuxt.js
v2
package.json
nuxt.config.js
在 页面 js 文件中使用:
v3
package.json
在开发模式下更新 .env 时,Nuxt 实例会自动重新启动以将新值应用于 process.env。
在您的应用程序代码中,您应该使用 运行时配置 而不是普通环境变量。
要将配置和环境变量公开到应用程序的其余部分,您需要在您的 nuxt.config 文件中使用 runtimeConfig 选项定义运行时配置。
当将 apiBase 添加到 runtimeConfig.public 时,Nuxt 会将其添加到每个页面有效负载中。我们可以在服务器端和浏览器端普遍访问 apiBase。
Reference
The text was updated successfully, but these errors were encountered: