React基礎筆記(二)

這是我參與8月更文挑戰的第2天,活動詳情查看:8月更文挑戰css

前言

本文做爲本人學習總結之用,同時分享給你們,適合入門的react小白
由於我的技術有限,若是有發現錯誤或存在疑問之處,歡迎指出或指點!不勝感謝!html

React腳手架

建立項目並啓動React項目

第一步,全局安裝:npm i -g create-react-app前端

第二步,切換到想創項目的目錄,使用命令:react

create-react-app hello-reactweb

yarn create react-app hello-reactajax

第三步,進入項目文件夾:cd hello-reactnpm

第四步,啓動項目:npm start 或者yarn start編程

配置代理

1.第一步:建立代理配置文件bootstrap

在src下建立配置文件:src/setupProxy.js後端

2.編寫setupProxy.js配置具體代理規則:

const proxy = require('http-proxy-middleware')

module.exports = function(app) {
  app.use(
    proxy('/api1', {  //api1是須要轉發的請求(全部帶有/api1前綴的請求都會轉發給5000)
      target: 'http://localhost:5000', //配置轉發目標地址(能返回數據的服務器地址)
      changeOrigin: true, //控制服務器接收到的請求頭中host字段的值
      /* changeOrigin設置爲true時,服務器收到的請求頭中的host爲:localhost:5000 changeOrigin設置爲false時,服務器收到的請求頭中的host爲:localhost:3000 changeOrigin默認值爲false,但咱們通常將changeOrigin值設爲true */
      pathRewrite: {'^/api1': ''} //去除請求前綴,保證交給後臺服務器的是正常請求地址(必須配置)
    }),
    proxy('/api2', { 
      target: 'http://localhost:5001',
      changeOrigin: true,
      pathRewrite: {'^/api2': ''}
    })
  )
}
複製代碼

說明:

  1. 優勢:能夠配置多個代理,能夠靈活的控制請求是否走代理。
  2. 缺點:配置繁瑣,前端請求資源時必須加前綴。

React-router

SPA

  1. React是單頁Web應用(single page web application,SPA)。
  2. 整個應用只有一個完整的頁面。
  3. 點擊頁面中的連接不會刷新頁面,只會作頁面的局部更新。
  4. 數據都須要經過ajax請求獲取, 並在前端異步展示。

前端路由

路由的概念來源於服務端,在服務端中路由描述的是 URL 與處理函數之間的映射關係。

在 Web 前端單頁應用 SPA中,路由描述的是 URL 與 UI 之間的映射關係,這種映射是單向的,即 URL 變化引發 UI 更新(無需刷新頁面)。

前端路由主要有兩種實現方案:hash、history

hash 實現

  • hash 是 URL 中 hash (#) 及後面的那部分,經常使用做錨點在頁面內進行導航,改變 URL 中的 hash 部分不會引發頁面刷新
  • 經過 hashchange 事件監聽 URL 的變化,改變 URL 的方式只有這幾種:經過瀏覽器前進後退改變 URL、經過<a>標籤改變 URL、經過window.location改變URL,這幾種狀況改變 URL 都會觸發 hashchange 事件

hash優缺點:

優勢:優勢: 實現簡單,兼容性好(兼容到 ie8) 絕大多數前端框架均提供了給予 hash 的路由實現 不須要服務器端進行任何設置和開發 除了資源加載和 ajax 請求之外,不會發起其餘請求

缺點: 對於部分須要重定向的操做,後端沒法獲取 hash 部份內容,致使後臺無 法取得 url 中的數據,典型的例子就是微信公衆號的 oauth 驗證 服務器端沒法準確跟蹤前端路由信息 對於須要錨點功能的需求會與目前路由機制衝突

history 實現

  • history 提供了 pushState 和 replaceState 兩個方法,這兩個方法改變 URL 的 path 部分不會引發頁面刷新

  • history 提供相似 hashchange 事件的 popstate 事件,但 popstate 事件有些不一樣:經過瀏覽器前進後退改變 URL 時會觸發 popstate 事件,經過pushState/replaceState或<a>標籤改變 URL 不會觸發 popstate 事件。好在咱們能夠攔截 pushState/replaceState的調用和<a>標籤的點擊事件來檢測 URL 變化,因此監聽 URL 變化能夠實現,只是沒有 hashchange 那麼方便

history 優缺點

優勢 :對於重定向過程當中不會丟失 url 中的參數。後端能夠拿到這部分數據。絕大多數前段框架均提供了 history 模式的路由實現。後端能夠準確跟蹤路由信息 可使用 history.state 來獲取當前 url 對應的狀態信息

缺點:兼容性不如 hash 路由(只兼容到 IE10) 須要後端支持,每次返回 html 文檔

簡單的說二者以前的區別

hash history
只修改#後面內容 能夠設置同源下任意的URL
新值不能與舊值相同,同樣的不會觸發動做將記錄添加到棧中 新舊值能夠相同,pushSate該添加的會添加到棧中
對服務器無需改動 刷新時,若服務器沒有響應數據或資源,會404。須要對服務器作一些改造,對不一樣的路由進行相應的設置。
即不會發送請求 會向服務器發送請求,避免404服務器應該作處理。當匹配不到資源時,應返回同一個html頁面。

react-router-dom

  1. react的一個插件庫。
  2. 專門用來實現一個SPA應用。
  3. 基於react的項目基本都會用到此庫。

安裝:yarn add react-router-dom 

內置組件--Link

1.導航區爲Link標籤 
 <Link className="list-group-item" to="/about">About</Link>
2.展現區寫Route標籤進行路徑的匹配
  <Route path="/about" component={About}/>
3.<App>的最外側包裹了一個<BrowserRouter>或<HashRouter>
//index.js
  ReactDOM.render(
    <BrowserRouter> <App/> </BrowserRouter>,
    document.getElementById('root')
)
複製代碼

內置組件--NavLink

跟link同樣的寫法

NavLink能夠實現路由連接的高亮,經過activeClassName指定樣式名

<NavLink activeClassName="atguigu" className="list-group-item" to="/about">About</NavLink>

//封裝組件 
//props中有children children正好是NavLink的屬性名顯示文字內容
<NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
//調用時
<MyNavLink to="/about">About</MyNavLink>
複製代碼

內置組件--switch

1.一般狀況下,path和component是一一對應的關係。

2.Switch能夠提升路由匹配效率(單一匹配)。 找到以後再也不繼續找尋

未使用Switch包裹註冊路由: 未匹配時,展現所有路由

image.png

具體編碼
{/* 註冊路由 */}
用Switch包裹以後僅出現Home組件
<Switch>
  <Route path="/about" component={About}/>
  <Route path="/home" component={Home}/>
  <Route path="/home" component={Test}/>
</Switch>
複製代碼

內置組件Redirect

通常寫在全部路由註冊的最下方,當全部路由都沒法匹配時,跳轉到Redirect指定的路由(重定向)

具體編碼
<Switch>
  <Route path="/about" component={About}/>
  <Route path="/home" component={Home}/>
  <Redirect to="/about"/>
</Switch>
複製代碼

解決多級路徑刷新頁面樣式丟失的問題

  1. public/index.html 中 引入樣式時不寫 ./ 寫 / (經常使用)
  2. public/index.html 中 引入樣式時不寫 ./ 寫 %PUBLIC_URL% (經常使用)
  3. 使用HashRouter (不建議使用)
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="stylesheet" href="/css/bootstrap.css"> ReactDOM.render( <HashRouter> <App/> </HashRouter>, document.getElementById('root') ) 複製代碼

路由的嚴格匹配與模糊匹配

  1. 默認使用的是模糊匹配(簡單記:【輸入的路徑】必須包含要【匹配的路徑】,且順序要一致)
  2. 開啓嚴格匹配:

<Route exact={true} path="/about" component={About}/>或者簡寫

<Route exact path="/about" component={About}/>

  1. 嚴格匹配不要隨便開啓,須要再開,有些時候開啓會致使沒法繼續匹配二級路由

嵌套路由

  1. 註冊子路由時要寫上父路由的path值
  2. 路由的匹配是按照註冊路由的順序進行的
//子路由的寫法
<Switch>
  <Route path="/home/news" component={News}/>
  <Route path="/home/message" component={Message}/>
  <Redirect to="/home/news"/>
</Switch>
複製代碼

路由組件傳遞參數

  1. params參數

    路由連接(攜帶參數):<Link to='/demo/test/tom/18'}>詳情</Link>

    註冊路由(聲明接收):<Route path="/demo/test/:name/:age" component={Test}/>

    接收參數:this.props.match.params

  2. search參數

    路由連接(攜帶參數):<Link to='/demo/test?name=tom&age=18'}>詳情</Link>

    註冊路由(無需聲明,正常註冊便可):<Route path="/demo/test" component={Test}/>

    接收參數:this.props.location.search

    備註:獲取到的search是urlencoded編碼字符串,須要藉助querystring解析

  3. state參數

     路由連接(攜帶參數):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>詳情</Link>

     註冊路由(無需聲明,正常註冊便可):<Route path="/demo/test" component={Test}/>

     接收參數:this.props.location.state

     備註:刷新也能夠保留住參數

具體編碼:
messageArr.map((msgObj)=>{
  return (
    <li key={msgObj.id}> {/* 向路由組件傳遞params參數 */} <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link> {/* 向路由組件傳遞search參數 */} <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link> {/* 向路由組件傳遞state參數 */} <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link> </li>
  )
})

{/* 聲明接收params參數 */}
<Route path="/home/message/detail/:id/:title" component={Detail}/>

{/* search參數無需聲明接收,正常註冊路由便可 */}
<Route path="/home/message/detail" component={Detail}/>

{/* state參數無需聲明接收,正常註冊路由便可 */}
<Route path="/home/message/detail" component={Detail}/>

子組件
import qs from 'querystring'
export default class Detail extends Component {
    render() {
        // 接收params參數
        const {id,title} = this.props.match.params 

        // 接收search參數
        const {search} = this.props.location
        const {id,title} = qs.parse(search.slice(1))

        // 接收state參數
        const {id,title} = this.props.location.state || {}

        const findResult = DetailData.find((detailObj)=>{
            return detailObj.id === id
        }) || {}
        return (
            <ul> <li>ID:{id}</li> <li>TITLE:{title}</li> <li>CONTENT:{findResult.content}</li> </ul>
        )
    }
}
複製代碼

編程式路由導航

  • push是往 history 裏面增長一層堆棧,能夠返回上一層
  • replace跳轉不會造成history,不可返回到上一層。
//藉助this.prosp.history對象上的API對操做路由跳轉、前進、後退
  this.prosp.history.push()  //push查看
        //push跳轉+攜帶params參數
        this.props.history.push(`/home/message/detail/${id}/${title}`)
        //push跳轉+攜帶search參數
        this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)
        //push跳轉+攜帶state參數
        this.props.history.push(`/home/message/detail`,{id,title})

  this.prosp.history.replace()  //replace查看
        //replace跳轉+攜帶params參數
        this.props.history.replace(`/home/message/detail/${id}/${title}`)
        //replace跳轉+攜帶search參數
        this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)
        //replace跳轉+攜帶state參數
        this.props.history.replace(`/home/message/detail`,{id,title})

  this.prosp.history.goBack()  //回退
  this.prosp.history.goForward() //前進
  this.prosp.history.go(n)  //負爲退 正爲進
複製代碼

BrowserRouter與HashRouter的區別

  1. 底層原理不同:
    • BrowserRouter使用的是H5的history API,不兼容IE9及如下版本。
    • HashRouter使用的是URL的哈希值。
  2. path表現形式不同
    • BrowserRouter的路徑中沒有# 例如:localhost:3000/demo/test
    • HashRouter的路徑包含# 例如:localhost:3000/#/demo/test
  3. 刷新後對路由state參數的影響
    • BrowserRouter沒有任何影響,由於state保存在history對象中。
    • HashRouter刷新後會致使路由state參數的丟失!!!
  4. 備註:HashRouter能夠用於解決一些路徑錯誤相關的問題。
相關文章
相關標籤/搜索