Next

笔记来自
技术胖视频
github项目

使用

  • react必须是16.x以上
  • 安装
npm install next react react-dom --save
  • 文件夹static,固定,所有的静态文件,图片都放在这里面,不会被打包进.next
  • css样式打包
npm install @zeit/next-css --save-dev
  • next.config.js
// 使用了这个之后,项目里使用到的css都会被打包到.next/static/css文件夹下
const withCSS = require('@zeit/next-css')

// fix: prevents error when .css files are required by node
if (typeof require !== 'undefined') {
  require.extensions['.css'] = (file) => {}
}

module.exports = withCss();
  • page/_app.js
// 这是入口文件,也就是第一加载的js
// 在这里引入css,router,redux
// 还有判断token等

import React from 'react'
import App from 'next/app'
import { Provider } from 'react-redux'
import withRedux  from 'next-redux-wrapper'
import { Router } from 'next/router'
import API from '../api/api'
import Layout from '../components/Layout'
import PageLoading from '../components/PageLoading'
import makeStore from '../store/store'
import {getJwt} from '../lib/auth'

class MyApp extends App {
  static async getInitialProps({Component, ctx,router}) {
        let {reduxStore,req} = ctx;
        let {dispatch} = reduxStore;
        let pageProps = {}
        let token = getJwt({req});
        if (Component.getInitialProps) {
            pageProps = await Component.getInitialProps(ctx)
        }
        if(token&&!!req){
            let res = await API.getUserInfo({token})
            if (res.data.code === 1) {
                let {username,avatar,_id} = res.data.data;
                dispatch(updateInfo({
                    avatar,
                    username,
                    userId:_id
                }))
            }
        }
        return { pageProps }
  }

  state = {
     loading: false
  }

  startLoading = () => {
     this.setState({
        loading: true
     })
  }
  stopLoading = () => {
     this.setState({
        loading: false
     })
  }
  componentDidMount () {
    Router.events.on('routeChangeStart', this.startLoading)
    Router.events.on('routeChangeComplete',this.stopLoading)
    Router.events.on('routeChangeError', this.stopLoading)
  }
  componentWillUnmount() {
    Router.events.off('routerChangeStart', this.startLoading)
    Router.events.off('routerChangeComplete',this.stopLoading)
    Router.events.off('routerChangeError', this.stopLoading)
  }

  render() {
     const {Component, pageProps, store} = this.props
     return (
        <div>
          <Provider store={store}>
            <Layout>
              { this.state.loading ? <PageLoading/> : null}
              <Component {...pageProps} />
            </Layout>
          </Provider>
       </div>
     )
   }
}

export default withRedux(makeStore)(MyApp);
  • 打包在.next文件夹下的文件会被自动生成一个html文件,渲染到浏览器端
  • 也可以自定义html
// _document.js
import Document, { Head, Main, NextScript } from 'next/document'

export default class MyDocument extends Document {
    render() {
        return (
            <html>
              <Head>
                // 这里不要设置title标签,原因往下看 
                <style>{
                    'body{color:red}'
                }</style>
              </Head>
              <body className="custom_class">
                 123123
                 <Main />
                 <NextScript />
              </body>
            </html>
        )
    }
}
  • 错误页面
// _error.js
// next自带_error.js这个可以在.next里找到这个页面,如果觉得不好看
// 重写就行

import React from 'react'

export default class Error extends React.Component {
  static async getInitialProps({ res, err }) {
    const statusCode = res ? res.statusCode : err ? err.statusCode : null;
    return { statusCode }
  }

  render() {
    return (
      <p>
        {this.props.statusCode
          ? `An error ${this.props.statusCode} occurred on server`
          : 'An error occurred on client'}
      </p>
    )
  }
}
  • 路由,跟nuxt一样,根据pages文件夹的文件摆放生成的,但是还是需要添加进路由里
pages/
--| _slug/
-----| index.vue
--| users/
-----| _id.vue // 注意这里是下划线
--| index.vue

// 生成
<Switch>
  <Route path="/" exact component={pages/index.jsx} />
  <Route path="/:slug" component={pages/_slug/index.jsx} />
  <Route path="/users/:id" component={pages/users/_id.jsx} />
</Switch>
  • 组件添加进路由里,添加redux
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Button,Icon, Tabs } from 'antd'
import { withRouter } from 'next/router'
import API from '../../api/api'
import { setArticles } from "../store/articles/action"

class LoginComponent extends Component {
  // 这是componentDidMount前的服务器生命周期
  static async getInitialProps({Component, ctx,router}) {
        let {reduxStore,req} = ctx;
        // 取值
        let article = reduxStore.getState().article
        let {dispatch} = reduxStore;
        let articleList = await API.getArticleList();
        // 更新
        dispatch(setArticles(articleList))
        // 这些数据都在this.props里
        return { articleList, article  }
  }
  state = { }
  render() {
    const { articleList,article} = this.props
    return (
        <div>
            // 如果想给页面添加title,就在return添加title标签
            <title>一个路由一个title</title>
            {resBlog}
        </div>
    )
}

export default connect(state => ({
  article: state.article,
}), {
  setArticles
})(withRouter(Text));
  • redux,跟redux一样,查看【JS/redux】笔记
// store/article/action.js
import * as article from './action-type';

export const setArticles = (articleList) => {
  return {
    type: article.SAVEFORMDATA,
    articleList: articleList,
  }
}

// store/article/action-type.js
export const SAVEFORMDATA = 'SAVEFORMDATA';

// store/article/reducer.js
import * as article from './action-type';

let defaultState = {
  article:"测试"
}
// 首页表单数据
export const article = (state = defaultState , action = {}) => {
  switch(action.type){
    case article.SAVEFORMDATA:
      // 这个state是defaultState,articleList是action.js传过来的
      // 这是个合并并更新defaultState的操作
      return {...state, ...{ articleList }};
    default:
      return state;
  }
}
  • server/index.js
// 起个服务器,不会的查看【Koa】笔记
const Koa = require('koa')
const next = require('next')
const Router = require('koa-router')
const Redis  = require('koa-redis')
const session = require('koa-session')
const json = require('koa-json')
const bodyParser = require('koa-bodyparser')

//开发状态
const port = 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })

//http响应
const handle = app.getRequestHandler()

//页面编译完成后响应请求
app.prepare().then(()=>{
  const server = new Koa()
  const router = new Router()
  server.proxy = true

  server.use(bodyParser({
    entableTypes: ['json','form','text']
  }))
  server.use(json())
  server.keys= ['_ayuan#']
  server.use(session(SESSION_CONFIG,server))

  // 接口路由
  router.get('/login', async (ctx) => {
     ...
  })

  server.use(router.routes())

  //监听
  server.use(async (ctx,next) => {
    ctx.req.session = ctx.session
    await handle(ctx.req, ctx.res)
    //不处理返回响应
    ctx.respond = false
  })

  server.listen(port,() => {
    console.log(`server is running on ${port}`)
  })
})
  • 启动服务
"scripts": {
  // 执行这个就会自动打包出.next文件夹
  "dev": "node ./server/index.js",
  "build": "next build",
  "start": "next start"
},

我还是不会用怎么办
把上面的github下载下来,没用的代码删了,改成自己的就行

posted @ 2020-06-11 11:27  一个年轻淫  阅读(235)  评论(0编辑  收藏  举报