国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

react-router 升級小記

isLishude / 771人閱讀

摘要:前言最近將公司項(xiàng)目的從版本升到了版本,跟完全不兼容,是一次徹底的重寫。升級過程中踩了不少的坑,也有一些值得分享的點(diǎn)。沒有就會(huì)匹配所有路由最后不得不說升級很困難,坑也很多。

前言

最近將公司項(xiàng)目的 react-router 從 v3 版本升到了 v4 版本,react-router v4 跟 v3 完全不兼容,是一次徹底的重寫。這也給升級造成了極大的困難,與其說升級不如說是對 router 層重寫。之前我也將項(xiàng)目的 react 從 v15 版本升級到了 v16 版本,相較而言升級 react-router 比升級 react 困難多了。升級過程中踩了不少的坑,也有一些值得分享的點(diǎn)。寫成一篇小文,供大家參考。

依賴升級

react-router v4 跟 react 一樣拆成了兩部分,核心的 react-router 和依運(yùn)行環(huán)境而定的 react-router-dom 或 react-router-native(跟 react-dom 和 react-native 一樣)。本文要說的是瀏覽器環(huán)境,也就是 react-router + react-router-dom

先安裝依賴(推薦使用 yarn)

yarn add react-router react-router-dom history

為什么要安裝 history 后面會(huì)解釋。

組件外導(dǎo)航與 react-router-redux

之前我們項(xiàng)目中使用了 react-router-redux 你有很多理由使用它,但對于我們來說唯一的理由或者用處就是用于在頁面組件之外導(dǎo)航,react-router-redux 讓你可以在任何地方通過 dispatch 處理頁面跳轉(zhuǎn),如:store.dispatch(push("/"))。因?yàn)檫@個(gè)我們就必須使用 react-router-redux 嗎?當(dāng)然不需要,有更簡單的辦法實(shí)現(xiàn)這個(gè)需求。所以這次升級我移除了react-router-redux, 寫作此文時(shí)支持 react-router v4 的 react-router-redux 還處于 v5.0.0-alpha.7 也是原因之一。

還記得之前安裝的 history 嗎?history 是 react-router 唯二的主要依賴之一,之所以要顯式安裝,是因?yàn)槲覀円褂盟鼇韺?shí)現(xiàn)頁面組件外導(dǎo)航。以下以 browser history 為例(hash history 和 memory history 都是一樣的):

我們不使用 react-router-dom 提供的 BrowserRouter 而是自己實(shí)現(xiàn)一個(gè)

// history.js
import createHistory from "history/createBrowserHistory";

const history = createHistory();

export default history;
// index.js
import React from "react";
import ReactDOM from "react-dom";
import { Router } from "react-router";
import history from "./history";
import App from "./app";

ReactDOM.render(
  
    
  ,
  document.getElementById("app")
);

搞定!就這么簡單,這樣在任何地方只要引用 history 就可以使用它進(jìn)行導(dǎo)航操作,如 history.push("/"),更多使用方式請參考 history 文檔。其實(shí) react-router-dom 的 BrowserRouter 跟我們做了同樣的事,區(qū)別在于我們這么做能把 history 暴露出來。這個(gè) history 就是頁面組件 props 里面的 history 自然也就能做同樣的事情。

靜態(tài)配置

react-router v3 是面向配置的,組件寫法只是一種語法糖。而 react-router v4 是完全面向組件的,提供的 Route Switch 等都是真正的組件。這也就導(dǎo)致只能按組件的方式寫路由,不能寫配置。但是 v3 那樣的配置確實(shí)有一些方便之處,如統(tǒng)一管理、使用方便等。

多虧 JSX 靈活的語法,我們依然有辦法按配置的方式寫 react-router v4 的路由。

// routes.js
import Home from "./home";
import About from "./about";
import Help from "./help";

export default [{
  path: "/",
  exact: true,
  component: Home
}, {
  path: "/about",
  component: About
}, {
  path: "/help",
  component: Help
}];
// app.js
import React from "react";
import { Switch, Route } from "react-router";
import routes from "./routes";
import NotFound from "./not-found";

class App extends React.Component {
  render() {
    return (
      
        {routes.map((route, i) => )}
        
      
    );
  }
}

export default App;

這樣我們就用配置的方式寫出了面向組件的路由,兼顧兩者的優(yōu)點(diǎn)。如果有嵌套路由需求,可以參考官方示例。官方也提供了一個(gè) react-router-config, 不過我沒有使用,一來覺得沒必要,二來寫作此文時(shí)它還處于 v1.0.0-beta.4 版本。

異步組件與 Code Splitting

Web 應(yīng)用最大的一個(gè)優(yōu)勢就是不必下載整個(gè)應(yīng)用,只用下載需要的部分就可以使用。要達(dá)到這樣的目標(biāo),就需要對代碼進(jìn)行分片,異步加載組件。可惜 react-router v4 沒有像 v3 一樣提供加載異步組件的接口。這部分工作就需要我們自己來處理。

我們可以創(chuàng)建一個(gè)高階組件 Bundle,專門用來加載異步組件。

// bundle.js
import React from "react";

class Bundle extends React.Component {
  constructor(props) {
    super(props);
    this.state = { Component: null };
    props.load().then(Component => this.setState({ Component: Component.default }));
  }
  render() {
    const { load, ...props } = this.props;
    const Component = this.state.Component;
    return Component ?  : null;
  }
}

export default Bundle;

然后修改一下 routes.js

// routes.js
import React from "react";
import Bundle from "./bundle";

export default [{
  path: "/",
  exact: true,
  component(props) {
    // 這里的 component 函數(shù)也是一個(gè)高階組件
    return  import("./home")} />;
  }
}, {
  path: "/about",
  component(props) {
    return  import("./about")} />;
  }
}, {
  path: "/help",
  component(props) {
    return  import("./help")} />;
  }
}];

這樣每個(gè)頁面都會(huì)打包成多帶帶的 JS,訪問相應(yīng)頁面才會(huì)去異步加載對應(yīng)的組件。這樣也可以做精細(xì)化緩存控制。
需要注意的是 import() 語法在寫作本文時(shí)還處于 Stage 2 的狀態(tài),需給 Babel 添加 syntax-dynamic-import 插件才能正常工作,另外需 webpack 2 及以上才支持。

查詢參數(shù)

因?yàn)楦鞣N原因 react-router v4 不再解析 ?key=value 這樣的 URL 的查詢參數(shù),頁面組件 props.location 中只有 search 字符串。這跟 v3 不兼容,而且很不方便。我們有辦法兼容一下嗎?當(dāng)然有,這時(shí)候之前寫的 histroy.js 又有新的用處了。

// history.js
import qs from "qs";
import createHistory from "history/createBrowserHistory";

function addQuery(history) {
  const location = history.location;
  history.location = { ...location, query: qs.parse(location.search, { ignoreQueryPrefix: true }) };
}

const history = createHistory();

addQuery(history);

export const unlisten = history.listen(() => {
  // 每次頁面跳轉(zhuǎn)都會(huì)執(zhí)行
  addQuery(history);
});

export default history;

這樣我們就能在頁面組件 props.location.query 拿到解析好的 URL 查詢參數(shù)了,跟 v3 完美兼容。還有個(gè)額外的好處是在任何地方引用 history 都可以拿到解析好的 URL 查詢參數(shù)。需要注意的是,在 history 的設(shè)計(jì)中,history 對象是 Mutable 的,所以我們可以直接修改 history。但是 history.location 是 Immutable 的,所以我們要確保每一個(gè) location 對象都是全新的。

搭配 Redux

react-router v4 跟 redux 搭配有一個(gè)大坑(mobx 應(yīng)該也有同樣的問題),詳情請看這篇文章,這里就不再贅述。簡單來說,如果一個(gè)組件用 redux 的 connect 包裝過,又?不是 Route 的子組件,那么 history 的變更就不會(huì)觸發(fā)這個(gè)組件的更新,它的子組件自然也不會(huì)更新。比如應(yīng)用的根組件(上文的 App)。

解決方案也很簡單,可以用 react-router v4 提供的 withRouter 再包裝一遍:withRouter(connect(...)(App)),或者讓 App 做為 Router 的子組件,原理都一樣。我采用的后者。

// app.js
import React from "react";
import { connect } from "react-redux";
import { Switch, Route } from "react-router";
import routes from "./routes";
import NotFound from "./not-found";

class App extends React.Component {
  render() {
    return (
      
        {routes.map((route, i) => )}
        
      
    );
  }
}

function mapStateToProps(state) {
  return {
    someState: state.someState
  };
}

export default connect(mapStateToProps)(App);
// index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { Router, Route } from "react-router";
import store from "./store";
import history from "./history";
import App from "./app";

ReactDOM.render(
  
    
       {/* 沒有 path 就會(huì)匹配所有路由 */}
    
  ,
  document.getElementById("app")
);
最后

不得不說升級 react-router 很困難,坑也很多。但是把坑一個(gè)個(gè)填完,最終完美升級也是一件很有意思,很有成就感的事。希望這篇文章能對你有所幫助。

另外完整的 Demo 請戳我的 GitHub,喜歡的話點(diǎn)個(gè) Star 吧 :P

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90533.html

相關(guān)文章

  • Vuex 升級入坑小記

    摘要:升級入坑小記場景描述引入的版本為,開啟調(diào)試工具默認(rèn)升級后可以調(diào)試。遂升級,發(fā)現(xiàn)大量使用失效,報(bào),的中文文檔,沒有及時(shí)更新。機(jī)票訂單和用戶信息。 Vuex 升級入坑小記 場景描述 引入Vuex的版本為0.3,開啟調(diào)試工具默認(rèn)升級后可以調(diào)試Vuex。給作者一個(gè)大大的贊。為提高開發(fā)體驗(yàn)也是操碎了心 (??????)?? (8。安利下(Vue Devtools)。 Vue Devtools ...

    ziwenxie 評論0 收藏0
  • gulp4.0升級小記

    摘要:前言周日在公司的新電腦在以前配置的目錄按下時(shí)發(fā)現(xiàn)報(bào)了錯(cuò),百度了一下得知原來已經(jīng)到了版本,就花了一點(diǎn)時(shí)間去升了個(gè)級,順便記下我個(gè)人使用到的配置文件新版本的不同點(diǎn),文筆和水平有限,多多見諒新引入新引入的可替換老版的和,代碼更簡潔是任務(wù)監(jiān)聽是任務(wù) 前言 周日在公司的新電腦在以前gulp3.9配置的目錄按下npm install時(shí)發(fā)現(xiàn)報(bào)了錯(cuò),百度了一下得知原來gulp已經(jīng)到了4.0版本,就花了...

    zorpan 評論0 收藏0
  • ReactRouter升級 v2 to v4

    摘要:概述相對于幾乎是重寫了新版的更偏向于組件化。汲取了很多思想,路由即是組件,使路由更具聲明式,且方便組合。如果你習(xí)慣使用,那么一定會(huì)很快上手新版的。被一分為三。不止是否有意義參考資料遷移到關(guān)注點(diǎn)官方文檔 概述 react-router V4 相對于react-router V2 or V3 幾乎是重寫了, 新版的react-router更偏向于組件化(everything is comp...

    JasonZhang 評論0 收藏0
  • async語法升級踩坑小記

    摘要:普通的回調(diào)函數(shù)調(diào)用執(zhí)行后續(xù)邏輯使用了以后的復(fù)雜邏輯獲取到正確的結(jié)果輸出兩個(gè)文件拼接后的內(nèi)容雖說解決了的問題,不會(huì)出現(xiàn)一個(gè)函數(shù)前邊有二三十個(gè)空格的縮進(jìn)。所以直接使用關(guān)鍵字替換原有的普通回調(diào)函數(shù)即可。 從今年過完年回來,三月份開始,就一直在做重構(gòu)相關(guān)的事情。 就在今天剛剛上線了最新一次的重構(gòu)代碼,希望高峰期安好,接近半年的Node.js代碼重構(gòu)。 包含從callback+async.w...

    VioletJack 評論0 收藏0
  • electron + react + react-router + mobx + webpack 搭

    摘要:調(diào)試集成環(huán)境選擇模塊,簡單分離開發(fā),測試,線上環(huán)境。程序保護(hù)開機(jī)自啟托盤最小化崩潰監(jiān)控升級一行代碼接入升級平臺,實(shí)現(xiàn)客戶端升級功能打包構(gòu)建一個(gè)指令搞定打包項(xiàng)目地址 項(xiàng)目地址 : https://github.com/ConardLi/electron-react electron-react electron + react + react-router + mobx + webpac...

    pingan8787 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<