Documents with learning next.js

Introduction: Next.js React is a lightweight server-side rendering application framework.

 

Next.js Chinese Click here

Next.js Chinese station Github Click here

New Folder to install it:

npm install --save next react react-dom

Add the following script to package.json in:

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

Note here. After starting the project services, react default port number is 3000, and the next entry files are hidden by default, this point later say. So if you already have a port project with the port number 3000, you can modify the script package.json:

{
  "scripts": {
    "dev": "next -p 2019",
    "build": "next build",
    "start": "next start"
  }
}

As above, after the add dev "-p port number" to;

Since Next.js only supports React 16 , we use properties React 16, so had to give up support for React 15 and the following versions.

Next.js has the following characteristics:

  • The default server-side rendering support
  • The code page is automatically divided
  • Simple client routing scheme (based on the page
  • Webpack-based development environment that supports hot replacement module
  • Perfectly integrated with Express or other Node.js server
  • Babel support and custom configuration options Webpack
  • It is the main file system API. Each .js file will become a route, automatic processing and rendering.
  • As a file server to pages render and index
  • Heat load
  • Static files.  ./static/ Mapped to  /static/ (you can create a static project folder in your project, which placed some pictures and fonts)

 Continue: New  ./pages/index.js to your project;

 

In our project, certainly more than one project. Then we need to jump between multiple pages, is necessary to use next/linkcomponents, let's add a new page game page and rewrite the index page;

game page

 

Link label support any components react as its child elements, not have to use a label, as long as the child elements can respond to onClick event, Link does not support adding style tags and attributes such as className, if you give the link an increasing pattern, it is necessary in the sub-elements Add to;

As the next hot-loaded, so you can save directly to see the effect oh;

Can now normal jump, then you need to pass parameters, and if you need to pass routing parameters, use the query stringform:

static async getInitialProps ({ req }) {
    const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
    return { userAgent }
  }

  render () {
    return (
      <div className="app-box">
        <p>我是next.js页面</p>
        <Link href="/game?title=hello">
          <a>To Game Page</a>
        </Link>
        <p>{this.props.userAgent}</p>
      </div>
    )
  }
static async getInitialProps ({ req, query }) {
    const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
    return { userAgent, query }
  }
  render () {
    console.log(this.props.query);
    return (
      <div className="game-box">
        <p>我是game页面</p>
        <Link href="/">
          <a>To index Page</a>
        </Link>
        <p>{this.props.query.title}</p>
      </div>
    )
  }

从上面两段代码可以看到:

  • 当页面渲染时加载数据,我们使用了一个异步方法getInitialProps。它能异步获取 JS 普通对象,并绑定在props上;
  • 当服务渲染时,getInitialProps将会把数据序列化,就像JSON.stringify。所以确保getInitialProps返回的是一个普通 JS 对象,而不是DateMap 或 Set类型;
  • 当页面初次加载时,getInitialProps只会在服务端执行一次。getInitialProps只有在路由切换的时候(如Link组件跳转或路由自定义跳转)时,客户端的才会被执行;
  • 当页面初始化加载时,getInitialProps只会加载在服务端。只有当路由跳转(Link组件跳转或 API 方法跳转)时,客户端才会执行getInitialProps;
  • 注意:getInitialProps将不能使用在子组件中。只能使用在pages页面中。

getInitialProps入参对象的属性如下:

  • pathname :URL 的 path 部分;
  • query : URL 的 query 部分,并被解析成对象;
  • asPath : 显示在浏览器中的实际路径(包含查询部分),为String类型;
  • req : HTTP 请求对象 (只有服务器端有);
  • res : HTTP 返回对象 (只有服务器端有);
  • jsonPageRes :获取数据响应对象(只有客户端有);
  • err : 渲染过程中的任何错误;

当然除了上面的Link跳转之外,还可以通过事件跳转,那么就需要借助next/router实现客户端路由切换:

import Router from 'next/router'

export default () =>
  <div>
    Click <span onClick={() => Router.push('/game')}>here</span> to read more
  </div>

这个Router对象的 API 如下:

  • route : 当前路由的String类型;
  • pathname : 不包含查询内容的当前路径,为String类型;
  • query : 查询内容,被解析成Object类型. 默认为{};
  • asPath : 展现在浏览器上的实际路径,包含查询内容,为String类型;
  • push(url, as=url) : 页面渲染第一个参数 url 的页面,浏览器栏显示的是第二个参数 url;
  • replace(url, as=url) : performs a replaceState call with the given url;
  • beforePopState(cb=function) : 在路由器处理事件之前拦截;

注意:Router.beforePopState() 截断Router操作的设置只有在客户端生效(需在componentDidMount中设置)且进入此函数中的方法只有Router栈中有值的时候才可以!

push 和 replace 函数的第二个参数as,是为了装饰 URL 作用。如果你在服务器端设置了自定义路由将会起作用;

 ok,通过上面的了解,我们已经学会了页面跳转的几种方式,既然可以跳转,那么可以监听跳转吗?即路由事件:

监听路由相关事件。 下面是事件支持列表:

  • routeChangeStart(url) --- 路由开始切换时触发
  • routeChangeComplete(url) --- 完成路由切换时触发
  • routeChangeError(err, url) --- 路由切换报错时触发
  • beforeHistoryChange(url) --- 浏览器 history 模式开始切换时触发
  • hashChangeStart(url) --- 开始切换 hash 值但是没有切换页面路由时触发
  • hashChangeComplete(url) --- 完成切换 hash 值但是没有切换页面路由时触发

我们尝试调用路由开始切换的事件:routeChangeStart

  // 监听路由开始切换时触发
  static onListenRouteChangeStart = () => {
    Router.events.on('routeChangeStart', (url) => {
      console.log('routerUrl' + url);
    });
  }

componentDidMount () { RouterApi.onListenRouteChangeStart(); }

如果不需要监听了,请释放它:Router.onRouteChangeStart = null;

既然都聊都了路由这块,那么就说说路由的另一个概念:浅层路由;

所谓浅路由模式,其实就是浅层路由允许你改变 URL 但是不执行getInitialProps生命周期。你可以加载相同页面的 URL,得到更新后的路由属性pathnamequery,并不失去 state 状态。

你可以给Router.push 或 Router.replace方法加如:shallow: true参数。如下面的例子所示:

const href = '/?counter=10'
const as = href
Router.push(href, as, { shallow: true });

现在 URL 更新为/?counter=10。在组件里查看this.props.router.query你将会看到更新的 URL。

需要注意的是:浅路由模式只支持相同的 URL,如果页面路由变化,还是会触发 getInitialProps;

更多的使用场景,可能类似与分页数据,我们只改变 page ,而不需要整个初始化。当然,我们可以监听:

componentWillReceiveProps(nextProps) {
  const { pathname, query } = nextProps.url
  // fetch data based on the new query
}

你可以在componentdidupdate钩子函数中监听 URL 的变化:

componentDidUpdate(prevProps) {
  const { pathname, query } = this.props.router
  // verify props have changed to avoid an infinite loop
  if (query.id !== prevProps.router.query.id) {
    // fetch data based on the new query
  }
}

对于路由的一些基本情况如上了,有具体问题具体分析;

那么下面我们来练习一下高阶组件:如果你想应用里每个组件都处理路由对象,你可以使用withRouter高阶组件。下面是如何使用它;

import React, { Component } from 'react';
import { withRouter } from 'next/router'

class RedEnvelope extends Component {
  render () {
    return (
      <div className="envelope-box">
        <p>我是红包组件</p>
        <h1>{this.props.router.query.title}</h1>
      </div>
    )
  }
}
export default withRouter(RedEnvelope);

我在game页面调用这个组件里面调用到this.props.router这个对象了:

 

ok,了解这些,就开始写项目吧,后面的配置和部署,接下来再更新

Guess you like

Origin www.cnblogs.com/thomas-yang-github/p/11358533.html