1. 程式人生 > 實用技巧 >create-react-app從一個新專案到一個請求

create-react-app從一個新專案到一個請求

  最近在學習react,想著畫些小頁面練練手,於是就想著拿些酷狗的api呼叫玩玩。

  首先命令列create-react-app appName建立一個名為appName的react專案。然後npm start執行專案,瀏覽器輸入localhost:3000可以看到頁面就ok了。

  按照官方demo說的,Edit src/App.js and save to reload。在src/App.js下隨便修改了文字,檢視頁面變化,似乎木有任何變化,瀏覽器重新整理才看到變化。沒有熱更新,忍不了,找到webpack文件,在入口檔案index.js中新增一段程式碼

//模組熱替換的API
if(module.hot){
  module.hot.accept();
}

  修改下程式碼ctrl+s儲存,看下頁面,瞬間很舒服。然後安裝axios,安裝react-router-dom,前者用來請求,後者用來設定頁面路由。

  npm install axios;

  npm installreact-router-dom;

  然後在src下新建plugins/axios/index.js,這步不配置也行,目前怎麼簡單怎麼來

import axios from 'axios';
axios.defaults.headers['Content-Type'] = 'application/json';


let config = {
  timeout: 60 * 1000, //
Timeout withCredentials: true, }; const _axios = axios.create(config); _axios.interceptors.request.use( (config) => { // Do something before request is sent config.headers['Authorization'] = ''; return config; }, (error) => { // Do something with request error return Promise.reject(error); } );
// Add a response interceptor _axios.interceptors.response.use( (response) => { // Do something with response data return response }, (error) => { // Do something with response error return Promise.reject(); } ); export default _axios;

  然後在入口檔案index.js引入

import axios from "./plugins/axios";

  然後修改下App.js,我這裡UI庫用的阿里的ant-design,之前vue用的都是ElemengUI,這次換個UI庫試玩玩。

import './App.css';
import {HashRouter, Route, Switch} from 'react-router-dom';
import React, {Component} from 'react';
import 'antd/dist/antd.css';
import { Layout, Menu, Breadcrumb } from 'antd';

import myMusic from './views/myMusic';
import discoverMusic from './views/discoverMusic'

const { Header, Content, Footer } = Layout;
class App extends Component  {
  render() {
    return (
      <Layout className="layout">
        <Header>
          <div className="logo">聚合音樂</div>
          <Menu theme="dark" mode="horizontal">
            <Menu.Item key="1"><a href='#/discoverMusic'>發現音樂</a></Menu.Item>
            <Menu.Item key="2"><a href='#/myMusic'>我的音樂</a></Menu.Item>
            <Menu.Item key="3"><a href='#/firstView'>樣式選擇</a></Menu.Item>
          </Menu>
        </Header>
        <Content style={{ padding: '0 50px' }}>
          <Breadcrumb style={{ margin: '16px 0' }}>
            <Breadcrumb.Item>Home</Breadcrumb.Item>
            <Breadcrumb.Item>List</Breadcrumb.Item>
            <Breadcrumb.Item>Music</Breadcrumb.Item>
          </Breadcrumb>
          <div className="site-layout-content">
          <HashRouter>
            <Switch>
                <Route exact path="/myMusic" component={myMusic}/>
                <Route exact path="/discoverMusic" component={discoverMusic}/>
            </Switch>
          </HashRouter>
          </div>
        </Content>
        <Footer style={{ textAlign: 'center' }}>Uni-Music App ©2020 Created by JDWu</Footer>
      </Layout>
    );
  }
}

export default App;

大致頁面顯示如下:

  discoverMusic中的程式碼為:

import { Input } from 'antd';
import { MehOutlined } from '@ant-design/icons';
import React from 'react';
import axios from 'axios'

const { Search } = Input;
class discoverMusic extends React.Component{
    constructor() {
        super();
        this.state = {
          inpValue: ""
        };
    }
    render() {
        return(
        <div>
            <Search
                placeholder="請輸入音樂名稱"
                style={InputWidth}
                enterButton="查詢"
                size="large"
                prefix={<MehOutlined />}
                onSearch={onSearch}/>
        </div>
        )
    }
}
const onSearch = value => {
    var params={
        format:'json',
        keyword:value,
        page:1,
        pagesize:20,
        showtype:1
    }
    axios.get('v3/search/song',{params:params}).then(data=>{
        console.log(data)
    })
}

const InputWidth={
    width:'30%',
}

export default discoverMusic

  注意這裡的axios請求,如果寫成axios.get('http://mobilecdn.kugou.com/api/v3/search/song')直接呼叫別人家的api就會出現一個老生常談的跨域問題。

  解決跨域的最簡單的方法就是在package.json中新增proxy欄位,這個只能在開發中使用,打包之後就沒啥用了,跨域就得靠nginx配置來實現了,我上述的程式碼就是這樣實現解決跨域問題的。

  網上還有一種比較複雜的:通過koa2-cors中介軟體進行代理轉發。這裡也記錄一下,畢竟也試了一水,畢竟誰都有個搞全棧的夢,前後端通吃是吧。

  安裝koa2,koa-router(請求路由,與react-router是兩個東西哦),koa-compose(洋蔥模型依賴於這個),koa2-cors(解決跨域的中介軟體)。

    npm install koa

    npm installkoa-router

    npm installkoa-compose

    npm installkoa2-cors

  然後在專案根目錄下新建server/server.js,routes.js,index.js三個檔案

  server.js程式碼:

const Koa= require('koa')
const app = new Koa()
const routes = require('./routes.js');
const cors = require('koa2-cors'); 
//執行跨域
app.use(cors());  
//路由
app.use(routes());
app.listen(3001,()=>{
    console.log('port is running at 3001')
})

  routes.js程式碼:

const compose = require('koa-compose');
const Router = require('koa-router');
var router = new Router();
const Index = require('./index');
router.get('/api/index', Index.index)
 
// app.use(router.routes()).use(router.allowedMethods());
module.exports = (ctx, next) => compose([router.routes(), router.allowedMethods()]);

  index.js程式碼:

const axios = require('axios')
class Index {
    static async index(ctx,next){
        const {format,keyword,page,pagesize,showtype} =ctx.request.query;
        const {data} = await axios.get('http://mobilecdn.kugou.com/api',{params:{
            format:format,
            keyword:keyword,
            page:page,
            pagesize:pagesize,
            showtype:showtype
        }})
        console.log(data)
        ctx.body=data
    }
}
module.exports = Index

則頁面的請求需要修改為:axios.get('http://localhost:3001/api/index')。然後命令列

  cd server 進入server資料夾

  node server.js 啟動koa服務端

看到port is running at 3001就代表koa後端服務啟動好了,然後就又可以愉快的發請求了。