前言
这篇文章将介绍Next.js中自定义App组件、Document组件以及什么时候需要自定义这些内容,这可能会是我们每个项目中都要做的事情,So,让我们一起掌握它吧。
Tips: 按照惯例声明,笔者也是个入门级选手,文章深度无法达到大佬级文章水平,只希望能对各位入门级的小伙伴有所帮助。
自定义App
首先说一下为什么要自定义App,这里的App其实就是我们平时写react时候的根组件。 1)通过重写
_app.js
文件,我们可以对App组件进行重构,在App组件中加入一些项目中不变的内容,比如页面的布局;2)在App中保持公用的状态,这里的公用状态也可以是一些全局的css,比如我们之前搭建环境的文章中加入的
antd.css
;3)以及给页面传递自定义的数据,
4)使用
componentDidCatch
自定义处理错误;5)注入额外数据到页面里 (如 GraphQL 查询)
在next.js+koa2+antd环境轻松搭建 一文中,我们曾经写过一个_app.js
来引入antd的css,在这里我们对除了引入antd.css
其他事情什么都没做,引入antd.css之后,它就会在全局生效。
import App from 'next/app'
import 'antd/dist/antd.css'
export default App
现在就来对它进行一些改变
import App, { Container } from 'next/app'
import 'antd/dist/antd.css'
// 新增了这一段
class MyApp extends App {
render() {
const { Component } = this.props;
console.log(Component);
return (
<Container>
<Component />
</Container>
)
}
}
export default MyApp
对比这一段代码,这里从next/app
中多引入了一个Container
组件,并在中间重新写了一个MyApp
类,继承自App,最后将其返回。在MyApp
中,重写了render
方法来渲染组件,其中从props中拿到的Component
组件就是在访问每个pages
下的js文件时候,这些文件返回的组件。想想也是,在写react的时候,其他组件要显示也是要包裹在最外层的App组件中的,这里是一样的道理。 值得注意的是,这里的MyApp组件返回Component时候最外层要使用Comtainer
组件进行包裹。我们可以顺手打印出Component,看看到底是不是向我们所说的一样。
重写getInitialProps
不过现在并不算完成,我们连App原本的功能还没实现完整:在当前组件中,我们是拿不到其他页面getInitialProps()
方法初始话的数据的,如果对getInitialProps()
不了解,请翻阅很简单的next.js数据获取规范或者官方文档 这里可以给大家看一个例子
这里在
getInitialProps()
中定义的数据并没有显示出来
class MyApp extends App {
static getInitialProps = async ({Component}) => {
let pageProps;
if(Component.getInitialProps) {
pageProps = await Component.getInitialProps()
}
return {
pageProps
}
}
render() {
const { Component, pageProps } = this.props;
console.log(Component);
return (
<Container> <Component {...pageProps} /> </Container>
)
}
}
这里在MyApp中新增了一个getInitialProps
方法,注意他是一个静态方法
,由于其他页面可能设置了getInitialProps
也可能没有设置,所以这里需要判断一下,并且这个方法为异步方法,执行时注意加上await
并在外层方法添加async
。这样就可以将其他页面中getInitialProps
设置的属性引入过来,并且传递给Component
就可以显示了,来看看效果吧
这里就可以正常打印了
管理全局数据举例
state = {
counter: 20
}
例如在MyApp中定义counter,就可以传递给所有组件 布局示例 在components目录下创建Layout.jsx
import Link from 'next/link';
import { Button } from 'antd'
export default ({ children }) => {
return (
<> <div className="header"> <Link href="/a?id=1"><Button>跳转A</Button></Link> <Link href="/test/b"><Button>跳转B</Button></Link> </div> <div className="body"> {children} </div> </>
)
}
然后在_app.js中引用
return (
<Container> <Layout> <Component {...pageProps} /> </Layout> </Container>
)
这样每个页面都会显示Layout了
自定义Document
只有在服务器端渲染的时候才会被调用,主要用来修改服务端渲染的文档内容,通常实现服务端渲染会使用一些
css-in-js
库(styled-jsx
是 Next.js自带默认使用的css-in-js库) 它在_document.js中定义
import Document, {Html, Head, Main, NextScript} from 'next/document'
class MyDocument extends Document {
render() {
return (
<Html> <Head> </Head> <body> <Main /> <NextScript /> </body> </Html>
)
}
}
export default MyDocument
在next/document
中提供的并不仅是Document组件,还有一些跟HTML标签对应的组件,在重写的时候要记得都要写上。
在Head中试着添加一些内容
<Head>
<title>My Next.js</title>
<style>{`* { color: red}`}</style>
</Head>
设置getInitialProps
再说明一下,document只有在服务端渲染时候才会执行。
在重写Docuemnt的时候,我们也可以重写getInitialProps
方法,这个getInitialProps来自于Document组件。
static getInitialProps = async (ctx) => {
const props = await Document.getInitialProps(ctx)
return {
...props
}
}
这里的getInitialProps也是个静态方法,并且也要加async,因为里面使用了await,并且注意有个参数ctx
,我们可以不重写它,但是如果我们要重写就要按照这个格式来重写,然后在里面再添加自己想要的东西。
结束
本文内容是比较简单的,但是很重要,在使用next.js开发项目中是要经常使用的,所以还是掌握好它吧。在后面集成
css in js
样式文章中可能还会再比较详细地描述在_docuemnt.js中我们可以干点什么,希望对入门级小伙伴有所帮助。
今天的文章必会的next.js自定义App和Document分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21470.html