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後端服務啟動好了,然後就又可以愉快的發請求了。