
Next.js 是一个轻量级的 React 服务端渲染应用框架。本教程演示使用Next.js制作一个显示比特币汇率的网站。详细的Next.js信息请访问https://nextjs.org/。
安装
本文假设你使用的是windows操作系统,已经安装npm。npm的安装方法,请自行bing搜索。
我使用的是visual studio code环境。命令行在该环境的terminal下输入、运行。当然你也可以使用其它环境如windows自带的powershell,使用写字板编辑代码。
新建一个名为BitzPrice目录,并进入该目录。
1  | C:\Users\HP\projects>mkdir bitzprice  | 
查看npm版本,确认你已经安装:
1  | PS C:\Users\HP\projects\bitzprices> npm --version  | 
初始化:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15PS C:\Users\HP\projects\bitzprices> npm init -y
Wrote to C:\Users\HP\projects\bitzprices\package.json:
{
  "name": "bitzprices",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
安装next、react和react-dom。某强国访问境外网站非常慢,建议使用国内镜像加速,当然也可以不用。
1  | PS C:\Users\HP\projects\bitzprices> npm config set registry https://registry.npm.taobao.org  | 
修改package.json
现在目录下应该有package.json文件了。修改这个文件,将scripts部分修改为:
1  | "scripts": {  | 
建立index页面
新建pages目录放置页面,在pages目录中新建Index.js文件,输入以下内容:
1  | export default () => (<div>Hello Next.js</div>)  | 
运行服务器
在terminal输入:
1  | bitzprices@1.0.0 dev C:\Users\HP\projects\bitzprices  | 
现在浏览器访问http://localhost:3000,应该可以看到以下画面:

新建about页面
在pages中新建文件About.js,输入以下内容:
1  | export default () => (<div>About BitzPrices</div>)  | 
在浏览器输入http://localhost:3000/about,会看到以下内容:
让代码更React化
Index.js修改成下面的样子:
1  | const Index = () => (  | 
现在访问页面,应该是这样:

About.js也做类似修改:
1  | const About = () => (  | 
About页面:
添加导航
我们使用next的Link作为导航。修改Index.js,内容如下:
1  | import Link from 'next/link';  | 
修改About.js内容如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14import Link from 'next/link';
const About = () => (
    <div>
        <ul>
            <li><Link href="/"><a>主页</a></Link></li>
            <li><Link href="/about"><a>关于</a></Link></li>
        </ul>
        <h1>关于BitzPrices</h1>
        <p>查看比特币汇率的应用。</p>
    </div>
);
export default About;
刷新浏览器页面,应该能够使用导航了。

将导航栏放入部件中
如果要创建多个页面,每个页面中都输入相同的代码显然太麻烦。我们可以将导航栏放入单独的部件,使用导航的页面只需要引入这个部件。
在bitzprices目录下新建components目录,在这个目录中新建Navbar.js文件,内容如下:
1  | import Link from 'next/link';  | 
Index.js现在只需要引入Navbar部件并使用它:
1  | import Navbar from '../components/Navbar';  | 
About.js也做相同修改。
使用样式表
我们在Navbar.js中展示样式表的使用,在文件中添加样式表,代码如下:
1  | import Link from 'next/link';  | 
现在的页面如下:

这个样式表只对Navbar这个部件有效,不影响其它地方的<ul>。
使用布局
在components目录下新建Layout.js文件,内容如下:
1  | import Navbar from './Navbar';  | 
我们对Index.js做如下修改:
1  | import Layout from '../components/Layout';  | 
About.js的修改也一样:1
2
3
4
5
6
7
8
9
10
11
12import Layout from '../components/Layout';
const About = () => (
    <Layout>
        <div>
            <h1>关于BitzPrices</h1>
            <p>查看比特币汇率的应用。</p>
        </div>
    </Layout>
);
export default About;
页面不会有任何变化,但我们现在已经使用布局了。
添加页面标题及样式表引用
修改Layout.js,引入Head,在Head中添加页面标题和样式表的引用(我们使用bootswatch的cerulean
)样式)。Layout.js的内容:
1  | import Head from 'next/head';  | 
刷新页面,
我们看到页面正文部分样式改变了,导航部分没有变。这是因为我们在Navbar.js中使用了样式表。为了应用cerulean样式,我们用cerulean的Navbar的源码代替Navbar.js的内容,注意要将所有的class=替换为className=,导航菜单内容及链接地址也做修改:
1  | const Navbar = () => (  | 
将页面内容放入容器
修改Layout.js,将{props.children}放入div中:
1  | <div className="container">  | 
通过API获取数据
我们要获取的数据来自https://www.coindesk.com/,地址为https://api.coindesk.com/v1/bpi/currentprice.json,通过这个地址获取的json数据为:1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"time":{
"updated":"Dec 8, 2019 02:06:00 UTC",
"updatedISO":"2019-12-08T02:06:00+00:00",
"updateduk":"Dec 8, 2019 at 02:06 GMT"
},
"disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
"chartName":"Bitcoin",
"bpi":{
"USD":{"code":"USD","symbol":"$","rate":"7,454.3000","description":"United States Dollar","rate_float":7454.3},
"GBP":{"code":"GBP","symbol":"£","rate":"5,674.7126","description":"British Pound Sterling","rate_float":5674.7126},
"EUR":{"code":"EUR","symbol":"€","rate":"6,740.6328","description":"Euro","rate_float":6740.6328}
}
}
获取数据,我们需要用到isomorphic-unfetch。安装:
1  | PS C:\Users\HP\projects\bitzprices> npm install isomorphic-unfetch  | 
修改Index.js如下:
1  | import Fetch from 'isomorphic-unfetch';  | 
刷新页面:
将Prices放入单独的部件
在components目录下,新建Prices.js文件,内容如下:
1  | class Prices extends React.Component {  | 
修改Index.js内容,1
2
3
4
5
6
7
8
9
10...
const Index = (props) => (
    <Layout>
        <div>
            <h1>欢迎访问 BitzPrices</h1>
            <Prices bpi={props.bpi} />
        </div>
    </Layout>
);
...
现在主页应该是这样:
显示汇率
修改Index.js内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import Fetch from 'isomorphic-unfetch';
import Layout from '../components/Layout';
import Prices from '../components/Prices';
const Index = (props) => (
    <Layout>
        <div>
            <h1>欢迎访问 BitzPrices</h1>
            <p>当前的比特币汇率:</p>
            <Prices bpi={props.bpi} />
        </div>
    </Layout>
);
Index.getInitialProps = async function() {
    const res = await Fetch(
        'https://api.coindesk.com/v1/bpi/currentprice.json'
    );
    const data = await res.json();
    return {
        bpi: data
    }
} 
export default Index;
修改Prices.js内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Prices extends React.Component {
    state = {
        currency: 'USD'
    }
    render() {
        return (<div>
            <ul className="list-group">
                <li className="list-group-item">
                    Bitcoin rate for {this.props.bpi.bpi.USD.description}:<span className="badge badge-primary">{this.props.bpi.bpi.USD.code}</span><strong>{this.props.bpi.bpi.USD.rate}</strong>
                </li>
            </ul>
        </div>);
    }
}
export default Prices;
刷新页面:
获取其它币种汇率
修改Prices.js,增加获取其它币种的数据:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class Prices extends React.Component {
    state = {
        currency: 'EUR'
    }
    render() {
        let list = '';
        if (this.state.currency === 'USD') {
            list = <li className="list-group-item"> Bitcoin rate for {this.props.bpi.bpi.USD.description}:<span className="badge badge-primary">{this.props.bpi.bpi.USD.code}</span><strong>{this.props.bpi.bpi.USD.rate}</strong></li>
        } else if (this.state.currency === 'GBP') {
            list = <li className="list-group-item"> Bitcoin rate for {this.props.bpi.bpi.GBP.description}:<span className="badge badge-primary">{this.props.bpi.bpi.GBP.code}</span><strong>{this.props.bpi.bpi.GBP.rate}</strong></li>
        } else if (this.state.currency === 'EUR') {
            list = <li className="list-group-item"> Bitcoin rate for {this.props.bpi.bpi.EUR.description}:<span className="badge badge-primary">{this.props.bpi.bpi.EUR.code}</span><strong>{this.props.bpi.bpi.EUR.rate}</strong></li>
        }
        return (<div>
            <ul className="list-group">
                {list}
            </ul>
        </div>);
    }
}
export default Prices;
现在,因为currency的值为EUR,刷新页面,应该能够看到如下画面:

动态选择要查询的币种
修改Prices.js,
1  | class Prices extends React.Component {  | 
现在可以选择要查询的币种了:

本文章内容参考了Traversy Media在Youtube上的视频。