https://juejin.cn/post/7203180600818581563
在用这个架构做了两个全栈项目后,整体要怎么开展做一个全栈项目已经很清楚了,但是原理还是一窍不通,只知道填空.因为机理不知道会导致找错误很难找,所以看了一堆文档学习了一下.

_app,tsx文档:

NextPage

NextPage 是 Next.js 提供的一个 TypeScript 类型,用于类型化页面组件。它扩展自 React 的 React.FunctionComponent(或简写为 React.FC),允许你为页面组件传递特定的 props 类型。这对于在 Next.js 应用中保持类型安全非常有帮助。

1
2
3
4
5
import { NextPage } from 'next';

const HomePage: NextPage<{ customProp: string }> = ({ customProp }) => {
return <div>{customProp}</div>;
};

在上面的例子中,HomePage 是一个 Next.js 页面,它预期有一个名为 customProp 的 prop

getLayout

getLayout 是一个非官方但在 Next.js 社区中广泛使用的模式,用于定义页面的布局。这个方法通常被定义在页面级别的组件上,返回一个函数,该函数接收当前页面作为参数,并返回一个封装了特定布局的 React 节点。

这种模式的好处是可以为不同的页面指定不同的布局,而不需要在每个页面中重复相同的布局代码。getLayout 函数可以被定义在 _app.js 或 _app.tsx 文件中的顶层应用组件里,用来应用各个页面特定的布局。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// pages/_app.js
import React from 'react';
import MainNav from '../components/MainNav';

function MyApp({ Component, pageProps }) {
const getLayout = Component.getLayout || ((page) => (
<div>
<MainNav /> // 在这里集中管理MainNav
{page}
</div>
));

return getLayout(<Component {...pageProps} />);
}

export default MyApp;

剩下的页面就不需要处理导航栏布局了
如果某个页面需要不同于全局默认的特殊布局,你可以在该页面中定义 getLayout 方法。例如,假设我们的“特殊页面”需要一个不同的页脚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// pages/specialPage.js
import React from 'react';
import SpecialFooter from '../components/SpecialFooter';

function SpecialPage() {
return (
<div>
<h1>Special Page Title</h1>
<p>This is some unique content for the special page.</p>
</div>
);
}


SpecialPage.getLayout = function getLayout(page) {
return (
<div>
{page}
<SpecialFooter /> // 特殊页脚只用于这个页面
</div>
);
}

export default SpecialPage;

AppProps

AppProps 是 Next.js 定义的一个类型,用于 _app.js 或 _app.tsx 中的顶层应用组件的 props。它包含了应用程序运行时所有页面公共的属性,如 Component, pageProps, 和 router 等。Component 属性代表当前激活的页面组件,而 pageProps 是预先加载的数据或初始 props,传递给 Component。

1
2
3
4
5
import { AppProps } from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}

在上面的例子中,MyApp 组件使用 AppProps 类型来保证类型安全,并且从 props 中接收 Component 和 pageProps,然后渲染当前的页面组件,传递给它必要的 props。

使用了 Next.js 默认提供的 AppProps 类型,这个类型已经足够应对大多数基本应用场景。它包括 Component 和 pageProps,这是用于渲染页面和传递页面级别数据的标准方式。

布局处理:因为没有定义 getLayout 方法的功能,所有页面将使用相同的布局方式。在这种情况下,全局布局只能通过修改 _app.tsx 文件本身来调整,不具备在页面级别上进行个性化布局调整的能力。
或者定义getlayout

MyApp 组件

MyApp 组件是 Next.js 应用的顶级组件,负责渲染所有页面。它使用上述类型以确保类型安全:

参数解构:从 props 中解构 Component 和 pageProps。

获取布局:尝试从页面组件(Component)获取 getLayout 方法,如果不存在,则使用一个默认函数,该函数直接返回传递给它的页面。

配置提供者:ConfigProvider 是一个 React 组件,用于设置全局配置。这里配置了主题,包括字体、主要颜色和表格的样式设置。
在 Next.js 的 _app.js 文件中,这行代码:

1
return <Component {...pageProps} />;

是用于动态渲染应用中的活动页面组件的核心表达式。这里面包含了几个关键的概念和 JavaScript 以及 React 的特性,我们逐一解析它们。

Component
在 Next.js 中,每个页面都是一个 React 组件。当用户导航到不同的路由时,对应的页面组件会成为 Component。这意味着 Component 是一个变量,它引用当前活动页面的顶级组件。

{…pageProps}
这是 JavaScript 的扩展运算符(Spread Operator)的一个用法。在这个上下文中,pageProps 是一个对象,包含了预先加载的页面的 props。这些 props 可能是在 getServerSideProps, getStaticProps 或者通过其他异步操作获得的。

使用扩展运算符 {…pageProps} 的目的是将 pageProps 对象中的每个键值对作为独立的 prop 传递给 Component。这样做的好处是无需明确知道 pageProps 中有哪些属性,就能保证所有的 props 都被透传到页面组件中。

组合使用 Component 和 {…pageProps}
将这两者组合在一起:

1
return <Component {...pageProps} />;

这行代码实现了在 Next.js 应用中动态渲染每个页面组件,并传递必要的 props 的功能。这是 Next.js 自定义 _app.js 的标准模式,它允许开发者在应用级别插入额外的逻辑(如全局状态管理、布局组件等),同时确保每个页面接收到其所需的 props。

实际示例
假设你有一个名为 About.js 的页面,它需要一个 user 对象作为 prop。如果你在 getServerSideProps 中为这个页面准备了 user 数据,pageProps 将是 { user: someUserData }。那么在 _app.js 中的这行代码会像这样工作:

1
return <About {...{ user: someUserData }} />;

这实质上等同于:

1
return <About user={someUserData} />;

这样,无论你有多少个页面,或者这些页面需要什么样的 props,_app.js 都能够将正确的 props 传递给正确的页面组件,而开发者无需对每个页面的 props 进行硬编码处理。
在 Next.js 中,pageProps 由 Next.js 自动处理并传递给 _app.js 或 app.tsx 文件,无论是否在页面级别使用了 getStaticProps 或 getServerSideProps。这意味着,pageProps 包含的内容将由具体的页面组件决定,并且这些属性会自动被聚合并传递给顶级的应用组件(即 MyApp)。这样设计的好处是能够确保每个页面的数据获取逻辑能够与应用的其他部分解耦,使得数据管理和页面渲染更加清晰。

总得来说,就是

Page组件

定义

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
// 在页面组件中
const Page = ({ children }) => <div>{children}</div>;
const Page = ({ children }) => (
<div className="page-container" style={{ margin: '20px', padding: '20px', border: '1px solid #ccc' }}>
{children}
</div>
);

export default Page;
//没有自己的 this 上下文:箭头函数不绑定自己的 this,它会捕获其所在上下文的 this 值,这使得它们非常适合用于那些不需要与 this 交互的场景,比如纯渲染组件。

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
import React from 'react';
import Page from './Page'; // 引入Page组件

function App() {
return (
<div>
<Page>
<h1>Welcome to Our Website</h1>
<p>This is a sample page demonstrating the use of the 'Page' component.</p>
</Page>
</div>
);
}