天天看點

02-HK租房 從0 到 102-HK租房 從0 到 1

02-HK租房 從0 到 1

本文是 hkzf 移動端 的系列教程,旨在通過一系列的文章來幫助初學者快速掌握基于React技術棧的項目開發。

路由配置

基本知識點

例子

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";
export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

        <hr />

        {/*
          A <Switch> looks through all its children <Route>
          elements and renders the first one whose path
          matches the current URL. Use a <Switch> any time
          you have multiple routes, but you want only one
          of them to render at a time
        */}
        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

// You can think of these components as "pages"
// in your app.

function Home() {
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}

function About() {
  return (
    <div>
      <h2>About</h2>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
    </div>
  );
}
           

兩種路由方式

import { BrowserRouter,HashRouter } from "react-router-dom"           
  1. HashRouter
  2. BrowserRouter

兩者的差別在與路由顯示方式不同:

HashRouter =>

https://bnpsd.csb.app/#/about

BrowserRouter =>

https://bnpsd.csb.app/about

三種渲染方式

在react-router的中,有3種渲染方式

  • component 每次渲染都會觸發元件的對應的生命周期
  • render 内聯模式渲染 props需要傳遞到函數内
  • children 一直渲染 props需要傳遞到函數内
<Route path="/home" component={Home} />
  <Route path="/home" render={(props) => <Home {...props} />}/>
  <Route path="/home" children={() => <About/>}/>           

HK項目中的路由配置

在HK項目src/App.js檔案中,可以找到對應的路由資訊,采用的是children的渲染模式,為每一個配置的

route

添加了關鍵字

exact

,精準比對每一個路由。

import React,{ Fragment } from "react"
import { HashRouter as Router,Route} from "react-router-dom"
import Home from "./pages/Home"
import List from "./pages/List"
import News from "./pages/News"
import Profile from "./pages/Profile"
import HKLayout from "./components/HKLayout"
import { getCityNameAction } from './store/actionCreator'
import BMap from './pages/BMap'
import CityList from './pages/CityList'

import store from "./store"


 export default class TabBarExample extends React.Component {


      componentDidMount(){
        this.getLocalCity();
      }
      getLocalCity = (params) => {
        let map = new window.BMap.LocalCity();
        map.get((result) => {
          const cityName = "廣州" || result.name;
          store.dispatch(getCityNameAction(cityName));
        }
        )

      }
      

      render(){
        return <Fragment>
          <Router>
            <Route path="/" exact render={()=> <HKLayout><Home/></HKLayout>}></Route>
            <Route path="/List" exact render={()=><HKLayout> <List/></HKLayout>}></Route>
            <Route path="/News" exact render={()=><HKLayout><News/></HKLayout>}></Route>
            <Route path="/Profile" exact render={()=><HKLayout><Profile/></HKLayout>}></Route>
            <Route path="/CityList" exact component={CityList}></Route>
            <Route path="/BMap" exact component={BMap}></Route>
          </Router>
        </Fragment>
      }

  }
           

環境變量配置

.env

檔案在由 creact-react-app 生成的項目裡是一個關于當環境的配置檔案,

我們可以在這個檔案裡寫一些配置,在實際開發中,我們會有開發、staging、生産等環境,每個環境的配置都不盡相同,最基本地,每個環境請求的後端伺服器的 url 就不相同,自己 mock 的時候的本機位址、與後端聯調時候的區域網路的位址,staging 的域名和正式上線環境的域名等等。

下面是對應的.env檔案的應用,.env一般是放置在項目根目錄下:

  • .env

    : 預設
  • .env.local

    : 本地變量 這個檔案是除了test之外會應用到的環境
  • .env.development

    ,

    .env.test

    .env.production

    : Environment-specific settings 環境特定的變量.
  • .env.development.local

    .env.test.local

    .env.production.local

    : 覆寫本地特定的環境變量

左邊的檔案比右邊的有更多優先權:

  • npm start

    :

    .env.development.local

    .env.development

    .env.local

    .env

  • npm run build

    .env.production.local

    .env.production

    .env.local

    .env

  • npm test

    .env.test.local

    .env.test

    .env

    (note

    .env.local

    is missing)

在HK項目中,我們配置了兩個配置檔案

.env.development

(用于開發環境)和

.env.production

(用于生産環境)

.env.development

REACT_APP_API_URL = http://hkzf.zbztb.cn           

.env.production

REACT_APP_API_URL = http://hkzf.zbztb.xxx           

在項目中使用

REACT_APP_API_URL

/**
 * 通用的接口url
 */
export  let REACT_APP_API_URL = process.env.REACT_APP_API_URL           

請求攔截器

axios中文文檔

預設配置

你指定的預設配置将會被應用到每個請求中

全局的axios配置

axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';           

自定義的預設執行個體

// Set config defaults when creating the instance
const instance = axios.create({
  baseURL: 'https://api.example.com'
});

// Alter defaults after instance has been created
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;           

配置的優先順序

配置将會以以下的優先順序被合并。預設配置在

lib/defaults.js

裡面可以找到。然後是執行個體的

defaults

屬性,之後就是請求的

config

參數。後者将會比前者優先權更高。下面是一個例子。

// Create an instance using the config defaults provided by the library
// At this point the timeout config value is `0` as is the default for the library
const instance = axios.create();

// Override timeout default for the library
// Now all requests using this instance will wait 2.5 seconds before timing out
instance.defaults.timeout = 2500;

// Override timeout for this request as it's known to take a long time
instance.get('/longRequest', {
  timeout: 5000
});           

Interceptors

你可以在請求或者響應被攔截前使用

then

或者

catch

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response;
  }, function (error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
    return Promise.reject(error);
  });           

如果你想移除一個攔截器你可以

const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);           

你可以添加一個攔截器到一個自定義的axios執行個體中。

const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});           

在HK項目中配置axios

src/utils/request.js

import Axios from "axios"
import { Toast } from "antd-mobile"
import { REACT_APP_API_URL } from "./urls"
//1. 配置一個通用的url
export let axios  = Axios.create({
    baseURL:REACT_APP_API_URL
})

//2. 請求攔截
axios.interceptors.request.use(function(config){
    Toast.loading("正在加載中...",1*60*60,null,true);
    return config;
},function(error){
    return Promise.reject(error)
})
//3. 傳回資料的攔截
axios.interceptors.response.use(function( res ){
    Toast.hide();
    return res.data;
},
function(error){
    return Promise.reject(error);
})