next.js 中的组件

next.js 里面的组件(页面)就是 react 里面的组件.

功能组件

在项目之中一个功能组件的创建 , 他可以和父组件放到一个文件里,也可以单独创建一个文件存放组件.

  • 没有生命周期
  • 没有 this
  • 没有 state 状态
  • 一个函数就是一个组件

功能组件一般作为展示类组件使用(轻,快)

import fetch from 'isomorphic-unfetch'

function Page({ stars }) {
return <div>Next stars: {stars}</div>
} Page.getInitialProps = async ({ req }) => {
const res = await fetch('https://api.github.com/repos/zeit/next.js')
const json = await res.json()
return { stars: json.stargazers_count }
} export default Page

类组件

通过 class 和 extends 继承来的组件,就是类组件.组件内部包含状态(state)且状态随着事件或者外部的消息.类组件带有生命周期(lifecycle),用以在不同的时刻触发状态的更新.这种组件一般用来写业务逻辑,根据不同的业务场景组件的状态数量以及生命周期机制也不尽相同.但是在 next 中由于是服务端渲染好组件之后发送给客户端使用的,所有生命周期实际上是从 componentDidMount 开始的.

下面是一个类组件

......

import React from 'react'

class HelloUA extends React.Component {
static async getInitialProps({ req }) {
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
return { userAgent }
} render() {
return <div>Hello World {this.props.userAgent}</div>
}
} export default HelloUA

getInitialProps

页面加载时加载数据,我们使用 getInitialProps 这种 async 静态方法.它可以异步获取数据并解析为 JavaScript Object 的形式添加到组件的 props 上.getInitialProps 服务器渲染时,将返回的数据进行序列化,类似于 JSON.stringify.确保返回的对象,是一个普通的 Object.对于初始页面加载,getInitialProps 仅在服务器上执行.getInitialProps 只有 在使用 Link 组件或使用路由 API 导航到其他路由时,才会在客户端上执行.

简单来说,初始化的请求一般放在服务端,页面显示在客户端之后的请求就放在客户端

  • getInitialProps 不能在子组件使用.仅支持 pages 下的页面组件.
  • 如果您使用某些仅用于服务器的模块 getInitialProps,不正确导入它们就会降低程序的速度.
  • pathname -URL 的路径部分
  • query -URL 的查询字符串部分(对象)
  • asPath- String 在浏览器中显示的实际路径(包括查询)
  • req -HTTP 请求对象(仅服务器)
  • res -HTTP 响应对象(仅服务器)
  • err -渲染期间遇到任何错误的错误对象

页面和动态页面

页面和动态页面就是一个组件,next 通过在 pages 下创建 js 文件来自动将组件与路由之间的匹配完成,减少了路由绑定这一步操作.

共享组件

共享组件就是公共组件,可以拿来复用的组件.一般我们在 components 文件夹下面创建这类组件,但是这与 pages 不同,并不是强制要求,你可以将你的共享组件在除 pages 之外的任何地方定义.

之前已经创建过 Header.js 和 MyLayout.js 两个布局,再新建一个 footer.js 组件,同时新建 components/layout 目录,将 3 个布局组件放进去

footer.js

export default () => <div className={["footer", "footer-main"]}></div>;

MyLayout.js

import React, { Component } from "react";
import Header from "./Header";
import Footer from "./Footer"; import "../../asserts/css/styles.less"; class Layout extends Component {
render() {
let { children } = this.props;
return (
<div>
<Header />
<div className={"content"}>{children}</div>
<Footer />
</div>
);
}
} export default Layout;

Header.js

import React, { Component } from "react";
import classnames from "classnames";
import { Menu, Button, Icon, Dropdown } from "antd";
import Link from "next/link";
import Router from "next/router"; const menu = (
<Menu>
<Menu.Item key="0">
<Link href="/">
<div>
<Icon type="user" />
我的主页
</div>
</Link>
</Menu.Item>
<Menu.Item key="1">
<Link href="/article">
<div>
<Icon type="user" />
我的专辑
</div>
</Link>
</Menu.Item>
<Menu.Item key="2">
<Link href="/about">
<div>
<Icon type="user" />
我的文章
</div>
</Link>
</Menu.Item>
<Menu.Divider />
<Menu.Item key="3">我的收藏</Menu.Item>
<Menu.Item key="4">我的钱包</Menu.Item>
<Menu.Item key="5">我的啥</Menu.Item>
<Menu.Item key="6">我的啥</Menu.Item>
<Menu.Divider />
<Menu.Item key="7">我的设置</Menu.Item>
<Menu.Item key="8">退出</Menu.Item>
</Menu>
); export default class Header extends Component {
constructor(props) {
super(props); this.state = {
active: "home" //home article collect
};
} changeActive(active) {
this.setState({
active
});
} render() {
return (
<div className={"nav nav-main header"}>
<div className={" header-inner"}>
<div className={"header-content"}>
<div className={"header-left"}>
<div className={"logo"}>
<img src="https://www.freelogodesign.org/Content/img/logo-samples/bakary.png" alt="logo"></img>
</div>
</div>
<div className="header-menu">
<div
onClick={() => {
this.changeActive("home");
}}
className={classnames({
"header-menu-item": true,
active: this.state.active === "home"
})}
>
<Link href="/">
<a>首页</a>
</Link>
</div>
<div
onClick={() => {
this.changeActive("collect");
}}
className={classnames({
"header-menu-item": true,
active: this.state.active === "collect"
})}
>
<Link href="/article">
<a>专辑</a>
</Link>
</div>
<div
onClick={() => {
this.changeActive("article");
}}
className={classnames({
"header-menu-item": true,
active: this.state.active === "article"
})}
>
<Link href="/article">
<a>文章</a>
</Link>
</div>
</div> <div className={"header-right"}>
<Dropdown overlay={menu} trigger={["click"]} placement="bottomCenter">
<div className={"avatar"}>
<img
src="https://images.xiaozhuanlan.com/photo/2019/2ad6384db0b94cd8e76d11194400df23.jpeg"
alt="avatar"
></img>
</div>
</Dropdown>
</div> <div className="header-btn">
<Button type="danger" ghost shape="round" icon="edit" onClick={() => Router.push("/write")}>
写文章>
</Button>
</div>
</div>
</div>
</div>
);
}
}

window(nagivator,localStorage) is not defined

  1. 将代码从 componentWillMount()移至 componentDidMount() (但是大多数问题都不是这个)

Next.js 是通用的,这意味着它首先在服务器端执行代码,然后在客户端执行代码.window 对象仅存在于客户端,因此,如果您需要在某些 React 组件中访问它,则应将该代码放在 componentDidMount 中.此生命周期方法仅在客户端上执行.

  1. 我一定要在 componentWillMount() 中执行
componentWillMount() {
if (typeof window !== 'undefined') {
console.log('window.innerHeight', window.innerHeight);
}
}
  1. 不使用 ssr

在使用富文本编辑器的时候出现这个问题,主要报错是在外部引入库中.

const DynamicComponentWithNoSSR = dynamic(
() => import('../components/eidtor'),
{ ssr: false }
) function Home() {
return (
<div>
<Header />
<DynamicComponentWithNoSSR />
<p>HOME PAGE is here!</p>
</div>
)
}

再次发布

当前机器已经存在 now 工具 , 直接执行 now 命令

now

输入网址,查看效果页面效果,需要注意的是 react-next-demo 和之前 next-demo 的区别,每次执行 now 之前需要修改项目名称,不然会自动覆盖前一个静态资源网站

Doc

[Next] 二.next.js之组件的更多相关文章

  1. js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable

    js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable 一.总结 一句话总结:bootstrap能够做为最火的框架,绝对不仅仅只有我看到的位置,它应该还有很多位置可 ...

  2. Blazor组件自做二 : 使用JS隔离制作手写签名组件

    Blazor组件自做二 : 使用JS隔离制作手写签名组件 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazor组件自做一 : 使用JS隔离 ...

  3. 免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)

    在生活中有一种东西几乎已经快要成为我们的另一个电子”身份证“,那就是二维码.无论是在软件开发的过程中,还是在普通用户的日常中,几乎都离不开二维码.二维码 (dimensional barcode) , ...

  4. 为Node.js编写组件的几种方式

    本文主要备忘为Node.js编写组件的三种实现:纯js实现.v8 API实现(同步&异步).借助swig框架实现. 关键字:Node.js.C++.v8.swig.异步.回调. 简介 首先介绍 ...

  5. DotNet二维码操作组件ThoughtWorks.QRCode

    DotNet二维码操作组件ThoughtWorks.QRCode 在生活中有一种东西几乎已经快要成为我们的另一个电子"身份证",那就是二维码.无论是在软件开发的过程中,还是在普通用 ...

  6. 小程序实践(二):swiper组件实现轮播图效果

    swiper组件类似于Android中的ViewPager,实现类似轮播图的效果,相对于Android的Viewpager,swiper实现起来更加方便,快捷. 效果图: 首先看下swiper支持的属 ...

  7. 【Vue.js实战案例】- Vue.js递归组件实现组织架构树和选人功能

    大家好!先上图看看本次案例的整体效果. 浪奔,浪流,万里涛涛江水永不休.如果在jq时代来实这个功能简直有些噩梦了,但是自从前端思想发展到现在的以MVVM为主流的大背景下,来实现一个这样繁杂的功能简直不 ...

  8. Ext.js高级组件

    第二章:Ext.js高级组件 grid组件 普通方式 表格面板类Ext.grid.Panel xtype(别名):gridpanel.grid title标题.renderTo渲染至.width宽.h ...

  9. 使用Vue CLI 3将基于element-ui二次封装的组件发布到npm

    前言:之前在网上找的好多都是基于vue-cli 2.x的,而使用vue-cli 3的文章比较少,Vue CLI 3 中文文档,所以我在自己尝试的时候把几篇文章结合了一下,调出来了我想要的模式,也就是V ...

随机推荐

  1. centos 6.8安装mysql5.6

    安装mysql 官方文档 A Quick Guide to Using the MySQL Yum Repository 下载 Yum Repository Go to the Download My ...

  2. 局域网 ARP 欺骗原理详解

    局域网 ARP 欺骗原理详解 ARP 欺骗是一种以 ARP 地址解析协议为基础的一种网络攻击方式, 那么什么是 ARP 地址解析协议: 首先我们要知道, 一台电脑主机要把以太网数据帧发送到同一局域网的 ...

  3. JavaScript事件兼容性写法

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. Android_(游戏)打飞机06:后续

    (游戏)打飞机01:前言 传送门 (游戏)打飞机02:游戏背景滚动 传送门 (游戏)打飞机03:控制玩家飞机 传送门 (游戏)打飞机04:绘画敌机.添加子弹   传送门 (游戏)打飞机05:处理子弹, ...

  5. java 从txt文本中随机获取名字

    代码: /* 获取随机文件文字 */ public static String random(String path) {//路径 String name = null; try { //把文本文件中 ...

  6. 20175215 2018-2019-2 第八周java课程学习总结

    第十五章 泛型与几何框架 15.1 泛型 泛型(Generics)是在JDK1.5中推出的,其主要目的是可以建立具有类型安全的集合框架,如链表.散列映射等数据结构. 15.1.1 泛型类声明 可以使用 ...

  7. LeetCode 14. 最长公共前缀(Longest Common Prefix)

    题目描述 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow ...

  8. 32位下操作mongodb心得

    本文出处:http://blog.csdn.net/chaijunkun/article/details/7236911,转载请注明. 随着互联网的变革,互联网的内容生成方式也逐渐地从网站生成转为用户 ...

  9. leetcode-easy-trees-108. Convert Sorted Array to Binary Search Tree

    mycode  81.75 # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x) ...

  10. 1.3 Junit4简介

    1.Junit4框架 可用于单元测试,直接测试类中的方法 2.简单实用 a.导入Junit的jar包 b.熟悉Junit的执行顺序 c.写测试用例 d.利用断言,找bug 3.demo public ...