必會的next.js自定義App和Document

前言

這篇文章將介紹Next.js中自定義App組件、Document組件以及何時須要自定義這些內容,這可能會是咱們每一個項目中都要作的事情,So,讓咱們一塊兒掌握它吧。javascript

Tips: 按照慣例聲明,筆者也是個入門級選手,文章深度沒法達到大佬級文章水平,只但願能對各位入門級的小夥伴有所幫助。css

自定義App

首先說一下爲何要自定義App,這裏的App其實就是咱們平時寫react時候的根組件。 1)經過重寫_app.js文件,咱們能夠對App組件進行重構,在App組件中加入一些項目中不變的內容,好比頁面的佈局;java

2)在App中保持公用的狀態,這裏的公用狀態也能夠是一些全局的css,好比咱們以前搭建環境的文章中加入的antd.cssreact

3)以及給頁面傳遞自定義的數據,服務器

4)使用componentDidCatch自定義處理錯誤;antd

5)注入額外數據到頁面裏 (如 GraphQL 查詢)app

next.js+koa2+antd環境輕鬆搭建 一文中,咱們曾經寫過一個_app.js來引入antd的css,在這裏咱們對除了引入antd.css其餘事情什麼都沒作,引入antd.css以後,它就會在全局生效。frontend

import App from 'next/app'
import 'antd/dist/antd.css'
export default App
複製代碼

如今就來對它進行一些改變koa

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中咱們能夠乾點什麼,但願對入門級小夥伴有所幫助。

相關文章
相關標籤/搜索