[React] 10 - Tutorial: router

  在安装react-router的时候加上一个5系列的版本号的,6版本api确实发生改变了,却不向下兼容,官方有点过分~

  意识到不妙的我赶紧去翻了翻react router的文档,发现react router早就在21年底就偷偷升级到了v6且变更极大。

 

Ref: REACT JS TUTORIAL #6 - React Router & Intro to Single Page Apps with React JS 

Ref: REACT JS TUTORIAL #7 - React Router Params & Queries

Ref: REACT JS TUTORIAL #8 - React Inline Styles & Component Arrays

Ref: react 技巧 #3 react-router 教程 part 1

Ref: react 技巧 #4 react-router 教程 part 2

Ref: reactjs/react-router-tutorial【官方版】

 

 

 

- 预 - 热 -


安装: react-router 

参考:npm使用教程,安装方法总结如下。

==npm安装==

npm install --save react-router
npm install --save react-router-dom
==yarn安装== yarn add react-router yarn add react-router-dom
==也可以使用React-Router CDN库==
<script src="https://unpkg.com/react-router/umd/ReactRouter.min.js"></script>

 

-S 就是--save的简写,就行npm 默认一个start 的字段,将包的名称及版本号放在 dependencies 里面。
-D 就是--save-dev 这样安装的包的名称及版本号就会存在package.json的 devDependencies 这个里面。

package.json

{
  "name"        : "react-tutorials",
  "version"     : "0.0.0",
  "description" : "",
  "main"        : "webpack.config.js",
  "dependencies"  : {
    "babel-core"  : "^6.17.0",
    "babel-loader": "^6.2.0",
    "babel-plugin-add-module-exports": "^0.1.2",
    "babel-plugin-react-html-attrs  ": "^2.0.0",
    "babel-plugin-transform-class-properties" : "^6.3.13",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-preset-es2015" : "^6.3.13",
    "babel-preset-react"  : "^6.3.13",
    "babel-preset-stage-0": "^6.3.13",
    "history"     : "^1.17.0",
    "react"       : "^0.14.6",
    "react-dom"   : "^0.14.6",
    "react-router": "^1.0.3",  // <---- 其实就是自动帮你写了,不用手动添加了
    "webpack"     : "^1.12.9",
    "webpack-dev-server": "^1.14.1"
  },
  "devDependencies": {
    "webpack-cli": "^2.1.3"
  },
  "scripts": {
    "dev": "webpack-dev-server --content-base src --inline --hot"
  },
  "author": "",
  "license": "ISC"
}
View Code

  

lolo@lolo-UX303UB$ npm run dev

unsw@unsw-UX303UB$ npm run dev

> react-tutorials@0.0.0 dev /media/unsw/CloudStorage/Linux-pan/ExtendedTmpSpace/Android-Workplace/android-and-ml/React-Native/demo-react/react-js-tutorials/2-react-router
> webpack-dev-server --content-base src --inline --hot

 http://localhost:8080/
webpack result is served from /
content is served from /media/unsw/CloudStorage/Linux-pan/ExtendedTmpSpace/Android-Workplace/android-and-ml/React-Native/demo-react/react-js-tutorials/2-react-router/src
Hash: d1bf073bfd493e36aea9
Version: webpack 1.15.0
Time: 3176ms
        Asset    Size  Chunks             Chunk Names
client.min.js  2.8 MB       0  [emitted]  main
chunk    {0} client.min.js (main) 1.02 MB [rendered]
    [0] multi main 52 bytes {0} [built]
    [1] (webpack)-dev-server/client?http://localhost:8080 4.16 kB {0} [built]
    [2] ./~/url/url.js 23.3 kB {0} [built]
    [3] ./~/url/~/punycode/punycode.js 14.6 kB {0} [built]
    [4] (webpack)/buildin/module.js 251 bytes {0} [built]
    [5] ./~/url/util.js 314 bytes {0} [built]
    [6] ./~/querystring/index.js 127 bytes {0} [built]
    [7] ./~/querystring/decode.js 2.4 kB {0} [built]
    [8] ./~/querystring/encode.js 2.09 kB {0} [built]
    [9] (webpack)-dev-server/~/strip-ansi/index.js 161 bytes {0} [built]
   [10] (webpack)-dev-server/~/ansi-regex/index.js 135 bytes {0} [built]
   [11] (webpack)-dev-server/client/socket.js 897 bytes {0} [built]
   [12] ./~/sockjs-client/lib/entry.js 244 bytes {0} [built]
   [13] ./~/sockjs-client/lib/transport-list.js 613 bytes {0} [built]
   [14] ./~/sockjs-client/lib/transport/websocket.js 2.72 kB {0} [built]
   [15] ./~/process/browser.js 5.42 kB {0} [built]
   [16] ./~/sockjs-client/lib/utils/event.js 2 kB {0} [built]
   [17] ./~/sockjs-client/lib/utils/random.js 746 bytes {0} [built]
   [18] ./~/sockjs-client/lib/utils/browser-crypto.js 438 bytes {0} [built]
   [19] ./~/sockjs-client/lib/utils/url.js 975 bytes {0} [built]
   [20] ./~/url-parse/index.js 11.5 kB {0} [built]
   [21] ./~/requires-port/index.js 753 bytes {0} [built]
   [22] ./~/url-parse/~/querystringify/index.js 1.58 kB {0} [built]
   [23] ./~/debug/src/browser.js 4.73 kB {0} [built]
   [24] ./~/debug/src/debug.js 4.39 kB {0} [built]
   [25] ./~/ms/index.js 2.76 kB {0} [built]
   [26] ./~/inherits/inherits_browser.js 672 bytes {0} [built]
   [27] ./~/sockjs-client/lib/event/emitter.js 1.27 kB {0} [built]
   [28] ./~/sockjs-client/lib/event/eventtarget.js 1.85 kB {0} [built]
   [29] ./~/sockjs-client/lib/transport/browser/websocket.js 210 bytes {0} [built]
   [30] ./~/sockjs-client/lib/transport/xhr-streaming.js 1.25 kB {0} [built]
   [31] ./~/sockjs-client/lib/transport/lib/ajax-based.js 1.31 kB {0} [built]
   [32] ./~/sockjs-client/lib/transport/lib/sender-receiver.js 1.18 kB {0} [built]
   [33] ./~/sockjs-client/lib/transport/lib/buffered-sender.js 2.3 kB {0} [built]
   [34] ./~/sockjs-client/lib/transport/lib/polling.js 1.32 kB {0} [built]
   [35] ./~/sockjs-client/lib/transport/receiver/xhr.js 1.58 kB {0} [built]
   [36] ./~/sockjs-client/lib/transport/sender/xhr-cors.js 343 bytes {0} [built]
   [37] ./~/sockjs-client/lib/transport/browser/abstract-xhr.js 4.8 kB {0} [built]
   [38] ./~/sockjs-client/lib/transport/sender/xhr-local.js 352 bytes {0} [built]
   [39] ./~/sockjs-client/lib/utils/browser.js 560 bytes {0} [built]
   [40] ./~/sockjs-client/lib/transport/xdr-streaming.js 984 bytes {0} [built]
   [41] ./~/sockjs-client/lib/transport/sender/xdr.js 2.46 kB {0} [built]
   [42] ./~/sockjs-client/lib/transport/eventsource.js 766 bytes {0} [built]
   [43] ./~/sockjs-client/lib/transport/receiver/eventsource.js 1.58 kB {0} [built]
   [44] ./~/sockjs-client/lib/transport/browser/eventsource.js 37 bytes {0} [built]
   [45] ./~/sockjs-client/lib/transport/lib/iframe-wrap.js 981 bytes {0} [built]
   [46] ./~/sockjs-client/lib/transport/iframe.js 3.83 kB {0} [built]
   [47] ./~/json3/lib/json3.js 43.3 kB {0} [built]
   [48] (webpack)/buildin/amd-options.js 43 bytes {0} [built]
   [49] ./~/sockjs-client/lib/version.js 26 bytes {0} [built]
   [50] ./~/sockjs-client/lib/utils/iframe.js 5.03 kB {0} [built]
   [51] ./~/sockjs-client/lib/utils/object.js 532 bytes {0} [built]
   [52] ./~/sockjs-client/lib/transport/htmlfile.js 710 bytes {0} [built]
   [53] ./~/sockjs-client/lib/transport/receiver/htmlfile.js 2.2 kB {0} [built]
   [54] ./~/sockjs-client/lib/transport/xhr-polling.js 894 bytes {0} [built]
   [55] ./~/sockjs-client/lib/transport/xdr-polling.js 712 bytes {0} [built]
   [56] ./~/sockjs-client/lib/transport/jsonp-polling.js 1.02 kB {0} [built]
   [57] ./~/sockjs-client/lib/transport/receiver/jsonp.js 5.57 kB {0} [built]
   [58] ./~/sockjs-client/lib/transport/sender/jsonp.js 2.46 kB {0} [built]
   [59] ./~/sockjs-client/lib/main.js 11.9 kB {0} [built]
   [60] ./~/sockjs-client/lib/shims.js 17.2 kB {0} [built]
   [61] ./~/sockjs-client/lib/utils/escape.js 2.36 kB {0} [built]
   [62] ./~/sockjs-client/lib/utils/transport.js 1.35 kB {0} [built]
   [63] ./~/sockjs-client/lib/utils/log.js 450 bytes {0} [built]
   [64] ./~/sockjs-client/lib/event/event.js 477 bytes {0} [built]
   [65] ./~/sockjs-client/lib/location.js 177 bytes {0} [built]
   [66] ./~/sockjs-client/lib/event/close.js 295 bytes {0} [built]
   [67] ./~/sockjs-client/lib/event/trans-message.js 292 bytes {0} [built]
   [68] ./~/sockjs-client/lib/info-receiver.js 2.22 kB {0} [built]
   [69] ./~/sockjs-client/lib/transport/sender/xhr-fake.js 456 bytes {0} [built]
   [70] ./~/sockjs-client/lib/info-iframe.js 1.52 kB {0} [built]
   [71] ./~/sockjs-client/lib/info-iframe-receiver.js 791 bytes {0} [built]
   [72] ./~/sockjs-client/lib/info-ajax.js 1.03 kB {0} [built]
   [73] ./~/sockjs-client/lib/iframe-bootstrap.js 2.9 kB {0} [built]
   [74] ./~/sockjs-client/lib/facade.js 723 bytes {0} [built]
   [75] (webpack)/hot/dev-server.js 1.85 kB {0} [built]
   [76] (webpack)/hot/log-apply-result.js 813 bytes {0} [built]
   [77] ./src/js/client.js 1.35 kB {0} [built]
   [78] ./~/react/react.js 56 bytes {0} [built]
   [79] ./~/react/lib/React.js 1.49 kB {0} [built]
   [80] ./~/react/lib/ReactDOM.js 3.71 kB {0} [built]
   [81] ./~/react/lib/ReactCurrentOwner.js 653 bytes {0} [built]
   [82] ./~/react/lib/ReactDOMTextComponent.js 4.32 kB {0} [built]
   [83] ./~/react/lib/DOMChildrenOperations.js 5 kB {0} [built]
   [84] ./~/react/lib/Danger.js 6.96 kB {0} [built]
   [85] ./~/fbjs/lib/ExecutionEnvironment.js 1.09 kB {0} [built]
   [86] ./~/fbjs/lib/createNodesFromMarkup.js 2.71 kB {0} [built]
   [87] ./~/fbjs/lib/createArrayFromMixed.js 2.36 kB {0} [built]
   [88] ./~/fbjs/lib/toArray.js 1.98 kB {0} [built]
   [89] ./~/fbjs/lib/invariant.js 1.51 kB {0} [built]
   [90] ./~/fbjs/lib/getMarkupWrap.js 3.06 kB {0} [built]
   [91] ./~/fbjs/lib/emptyFunction.js 1.09 kB {0} [built]
   [92] ./~/react/lib/ReactMultiChildUpdateTypes.js 861 bytes {0} [built]
   [93] ./~/fbjs/lib/keyMirror.js 1.27 kB {0} [built]
   [94] ./~/react/lib/ReactPerf.js 2.51 kB {0} [built]
   [95] ./~/react/lib/setInnerHTML.js 3.35 kB {0} [built]
   [96] ./~/react/lib/setTextContent.js 1.2 kB {0} [built]
   [97] ./~/react/lib/escapeTextContentForBrowser.js 849 bytes {0} [built]
   [98] ./~/react/lib/DOMPropertyOperations.js 7.88 kB {0} [built]
   [99] ./~/react/lib/DOMProperty.js 9.57 kB {0} [built]
  [100] ./~/react/lib/quoteAttributeValueForBrowser.js 746 bytes {0} [built]
  [101] ./~/fbjs/lib/warning.js 1.77 kB {0} [built]
  [102] ./~/react/lib/ReactComponentBrowserEnvironment.js 1.26 kB {0} [built]
  [103] ./~/react/lib/ReactDOMIDOperations.js 3.29 kB {0} [built]
  [104] ./~/react/lib/ReactMount.js 36.8 kB {0} [built]
  [105] ./~/react/lib/ReactBrowserEventEmitter.js 12.4 kB {0} [built]
  [106] ./~/react/lib/EventConstants.js 2.04 kB {0} [built]
  [107] ./~/react/lib/EventPluginHub.js 9.22 kB {0} [built]
  [108] ./~/react/lib/EventPluginRegistry.js 8.41 kB {0} [built]
  [109] ./~/react/lib/EventPluginUtils.js 6.79 kB {0} [built]
  [110] ./~/react/lib/ReactErrorUtils.js 2.27 kB {0} [built]
  [111] ./~/react/lib/accumulateInto.js 1.74 kB {0} [built]
  [112] ./~/react/lib/forEachAccumulated.js 893 bytes {0} [built]
  [113] ./~/react/lib/ReactEventEmitterMixin.js 1.3 kB {0} [built]
  [114] ./~/react/lib/ViewportMetrics.js 638 bytes {0} [built]
  [115] ./~/react/lib/Object.assign.js 1.26 kB {0} [built]
  [116] ./~/react/lib/isEventSupported.js 1.97 kB {0} [built]
  [117] ./~/react/lib/ReactDOMFeatureFlags.js 458 bytes {0} [built]
  [118] ./~/react/lib/ReactElement.js 8.07 kB {0} [built]
  [119] ./~/react/lib/canDefineProperty.js 629 bytes {0} [built]
  [120] ./~/react/lib/ReactEmptyComponentRegistry.js 1.38 kB {0} [built]
  [121] ./~/react/lib/ReactInstanceHandles.js 10.6 kB {0} [built]
  [122] ./~/react/lib/ReactRootIndex.js 723 bytes {0} [built]
  [123] ./~/react/lib/ReactInstanceMap.js 1.25 kB {0} [built]
  [124] ./~/react/lib/ReactMarkupChecksum.js 1.39 kB {0} [built]
  [125] ./~/react/lib/adler32.js 1.2 kB {0} [built]
  [126] ./~/react/lib/ReactReconciler.js 3.55 kB {0} [built]
  [127] ./~/react/lib/ReactRef.js 2.34 kB {0} [built]
  [128] ./~/react/lib/ReactOwner.js 3.45 kB {0} [built]
  [129] ./~/react/lib/ReactUpdateQueue.js 10.9 kB {0} [built]
  [130] ./~/react/lib/ReactUpdates.js 8.54 kB {0} [built]
  [131] ./~/react/lib/CallbackQueue.js 2.44 kB {0} [built]
  [132] ./~/react/lib/PooledClass.js 3.55 kB {0} [built]
  [133] ./~/react/lib/Transaction.js 9.55 kB {0} [built]
  [134] ./~/fbjs/lib/emptyObject.js 482 bytes {0} [built]
  [135] ./~/fbjs/lib/containsNode.js 1.43 kB {0} [built]
  [136] ./~/fbjs/lib/isTextNode.js 628 bytes {0} [built]
  [137] ./~/fbjs/lib/isNode.js 712 bytes {0} [built]
  [138] ./~/react/lib/instantiateReactComponent.js 4.52 kB {0} [built]
  [139] ./~/react/lib/ReactCompositeComponent.js 27.5 kB {0} [built]
  [140] ./~/react/lib/ReactComponentEnvironment.js 1.67 kB {0} [built]
  [141] ./~/react/lib/ReactPropTypeLocations.js 549 bytes {0} [built]
  [142] ./~/react/lib/ReactPropTypeLocationNames.js 611 bytes {0} [built]
  [143] ./~/react/lib/shouldUpdateReactComponent.js 1.49 kB {0} [built]
  [144] ./~/react/lib/ReactEmptyComponent.js 1.8 kB {0} [built]
  [145] ./~/react/lib/ReactNativeComponent.js 3.02 kB {0} [built]
  [146] ./~/react/lib/validateDOMNesting.js 13.1 kB {0} [built]
  [147] ./~/react/lib/ReactDefaultInjection.js 3.99 kB {0} [built]
  [148] ./~/react/lib/BeforeInputEventPlugin.js 14.9 kB {0} [built]
  [149] ./~/react/lib/EventPropagators.js 5.22 kB {0} [built]
  [150] ./~/react/lib/FallbackCompositionState.js 2.49 kB {0} [built]
  [151] ./~/react/lib/getTextContentAccessor.js 994 bytes {0} [built]
  [152] ./~/react/lib/SyntheticCompositionEvent.js 1.16 kB {0} [built]
  [153] ./~/react/lib/SyntheticEvent.js 5.79 kB {0} [built]
  [154] ./~/react/lib/SyntheticInputEvent.js 1.15 kB {0} [built]
  [155] ./~/fbjs/lib/keyOf.js 1.11 kB {0} [built]
  [156] ./~/react/lib/ChangeEventPlugin.js 11.5 kB {0} [built]
  [157] ./~/react/lib/getEventTarget.js 930 bytes {0} [built]
  [158] ./~/react/lib/isTextInputElement.js 1.03 kB {0} [built]
  [159] ./~/react/lib/ClientReactRootIndex.js 551 bytes {0} [built]
  [160] ./~/react/lib/DefaultEventPluginOrder.js 1.26 kB {0} [built]
  [161] ./~/react/lib/EnterLeaveEventPlugin.js 3.9 kB {0} [built]
  [162] ./~/react/lib/SyntheticMouseEvent.js 2.2 kB {0} [built]
  [163] ./~/react/lib/SyntheticUIEvent.js 1.64 kB {0} [built]
  [164] ./~/react/lib/getEventModifierState.js 1.3 kB {0} [built]
  [165] ./~/react/lib/HTMLDOMPropertyConfig.js 7.63 kB {0} [built]
  [166] ./~/react/lib/ReactBrowserComponentMixin.js 1.15 kB {0} [built]
  [167] ./~/react/lib/findDOMNode.js 2.17 kB {0} [built]
  [168] ./~/react/lib/ReactDefaultBatchingStrategy.js 1.92 kB {0} [built]
  [169] ./~/react/lib/ReactDOMComponent.js 36.9 kB {0} [built]
  [170] ./~/react/lib/AutoFocusUtils.js 816 bytes {0} [built]
  [171] ./~/fbjs/lib/focusNode.js 725 bytes {0} [built]
  [172] ./~/react/lib/CSSPropertyOperations.js 5.71 kB {0} [built]
  [173] ./~/react/lib/CSSProperty.js 3.5 kB {0} [built]
  [174] ./~/fbjs/lib/camelizeStyleName.js 1.03 kB {0} [built]
  [175] ./~/fbjs/lib/camelize.js 729 bytes {0} [built]
  [176] ./~/react/lib/dangerousStyleValue.js 1.93 kB {0} [built]
  [177] ./~/fbjs/lib/hyphenateStyleName.js 1 kB {0} [built]
  [178] ./~/fbjs/lib/hyphenate.js 822 bytes {0} [built]
  [179] ./~/fbjs/lib/memoizeStringOnly.js 778 bytes {0} [built]
  [180] ./~/react/lib/ReactDOMButton.js 1.15 kB {0} [built]
  [181] ./~/react/lib/ReactDOMInput.js 5.74 kB {0} [built]
  [182] ./~/react/lib/LinkedValueUtils.js 5.23 kB {0} [built]
  [183] ./~/react/lib/ReactPropTypes.js 12.5 kB {0} [built]
  [184] ./~/react/lib/getIteratorFn.js 1.17 kB {0} [built]
  [185] ./~/react/lib/ReactDOMOption.js 2.82 kB {0} [built]
  [186] ./~/react/lib/ReactChildren.js 5.83 kB {0} [built]
  [187] ./~/react/lib/traverseAllChildren.js 6.9 kB {0} [built]
  [188] ./~/react/lib/ReactDOMSelect.js 6.11 kB {0} [built]
  [189] ./~/react/lib/ReactDOMTextarea.js 4.35 kB {0} [built]
  [190] ./~/react/lib/ReactMultiChild.js 14.7 kB {0} [built]
  [191] ./~/react/lib/ReactChildReconciler.js 4.52 kB {0} [built]
  [192] ./~/react/lib/flattenChildren.js 1.65 kB {0} [built]
  [193] ./~/fbjs/lib/shallowEqual.js 1.28 kB {0} [built]
  [194] ./~/react/lib/ReactEventListener.js 7.51 kB {0} [built]
  [195] ./~/fbjs/lib/EventListener.js 2.65 kB {0} [built]
  [196] ./~/fbjs/lib/getUnboundedScrollPosition.js 1.09 kB {0} [built]
  [197] ./~/react/lib/ReactInjection.js 1.37 kB {0} [built]
  [198] ./~/react/lib/ReactClass.js 27.8 kB {0} [built]
  [199] ./~/react/lib/ReactComponent.js 5.04 kB {0} [built]
  [200] ./~/react/lib/ReactNoopUpdateQueue.js 3.94 kB {0} [built]
  [201] ./~/react/lib/ReactReconcileTransaction.js 4.58 kB {0} [built]
  [202] ./~/react/lib/ReactInputSelection.js 4.32 kB {0} [built]
  [203] ./~/react/lib/ReactDOMSelection.js 6.83 kB {0} [built]
  [204] ./~/react/lib/getNodeForCharacterOffset.js 1.66 kB {0} [built]
  [205] ./~/fbjs/lib/getActiveElement.js 924 bytes {0} [built]
  [206] ./~/react/lib/SelectEventPlugin.js 6.71 kB {0} [built]
  [207] ./~/react/lib/ServerReactRootIndex.js 868 bytes {0} [built]
  [208] ./~/react/lib/SimpleEventPlugin.js 17.4 kB {0} [built]
  [209] ./~/react/lib/SyntheticClipboardEvent.js 1.23 kB {0} [built]
  [210] ./~/react/lib/SyntheticFocusEvent.js 1.12 kB {0} [built]
  [211] ./~/react/lib/SyntheticKeyboardEvent.js 2.76 kB {0} [built]
  [212] ./~/react/lib/getEventCharCode.js 1.56 kB {0} [built]
  [213] ./~/react/lib/getEventKey.js 2.93 kB {0} [built]
  [214] ./~/react/lib/SyntheticDragEvent.js 1.13 kB {0} [built]
  [215] ./~/react/lib/SyntheticTouchEvent.js 1.33 kB {0} [built]
  [216] ./~/react/lib/SyntheticWheelEvent.js 1.99 kB {0} [built]
  [217] ./~/react/lib/SVGDOMPropertyConfig.js 3.8 kB {0} [built]
  [218] ./~/react/lib/ReactDefaultPerf.js 8.63 kB {0} [built]
  [219] ./~/react/lib/ReactDefaultPerfAnalysis.js 5.79 kB {0} [built]
  [220] ./~/fbjs/lib/performanceNow.js 844 bytes {0} [built]
  [221] ./~/fbjs/lib/performance.js 612 bytes {0} [built]
  [222] ./~/react/lib/ReactVersion.js 379 bytes {0} [built]
  [223] ./~/react/lib/renderSubtreeIntoContainer.js 463 bytes {0} [built]
  [224] ./~/react/lib/ReactDOMServer.js 766 bytes {0} [built]
  [225] ./~/react/lib/ReactServerRendering.js 3.3 kB {0} [built]
  [226] ./~/react/lib/ReactServerBatchingStrategy.js 673 bytes {0} [built]
  [227] ./~/react/lib/ReactServerRenderingTransaction.js 2.3 kB {0} [built]
  [228] ./~/react/lib/ReactIsomorphic.js 2.05 kB {0} [built]
  [229] ./~/react/lib/ReactDOMFactories.js 3.36 kB {0} [built]
  [230] ./~/react/lib/ReactElementValidator.js 10.8 kB {0} [built]
  [231] ./~/fbjs/lib/mapObject.js 1.47 kB {0} [built]
  [232] ./~/react/lib/onlyChild.js 1.21 kB {0} [built]
  [233] ./~/react/lib/deprecated.js 1.77 kB {0} [built]
  [234] ./~/react-dom/index.js 63 bytes {0} [built]
  [235] ./~/react-router/lib/index.js 2.38 kB {0} [built]
  [236] ./~/react-router/lib/Router.js 5.82 kB {0} [built]
  [237] ./~/warning/browser.js 1.81 kB {0} [built]
  [238] ./~/history/lib/createHashHistory.js 7.5 kB {0} [built]
  [239] ./~/invariant/browser.js 1.4 kB {0} [built]
  [240] ./~/history/lib/Actions.js 720 bytes {0} [built]
  [241] ./~/history/lib/ExecutionEnvironment.js 175 bytes {0} [built]
  [242] ./~/history/lib/DOMUtils.js 2.5 kB {0} [built]
  [243] ./~/history/lib/DOMStateStorage.js 2.01 kB {0} [built]
  [244] ./~/history/lib/createDOMHistory.js 1.29 kB {0} [built]
  [245] ./~/history/lib/createHistory.js 8.35 kB {0} [built]
  [246] ./~/deep-equal/index.js 3.05 kB {0} [built]
  [247] ./~/deep-equal/lib/keys.js 202 bytes {0} [built]
  [248] ./~/deep-equal/lib/is_arguments.js 641 bytes {0} [built]
  [249] ./~/history/lib/AsyncUtils.js 441 bytes {0} [built]
  [250] ./~/history/lib/createLocation.js 1.72 kB {0} [built]
  [251] ./~/history/lib/parsePath.js 1.16 kB {0} [built]
  [252] ./~/history/lib/extractPath.js 278 bytes {0} [built]
  [253] ./~/history/lib/runTransitionHook.js 775 bytes {0} [built]
  [254] ./~/history/lib/deprecate.js 299 bytes {0} [built]
  [255] ./~/react-router/lib/RouteUtils.js 3.49 kB {0} [built]
  [256] ./~/react-router/lib/RoutingContext.js 4.85 kB {0} [built]
  [257] ./~/react-router/lib/getRouteParams.js 578 bytes {0} [built]
  [258] ./~/react-router/lib/PatternUtils.js 6.79 kB {0} [built]
  [259] ./~/react-router/lib/useRoutes.js 10 kB {0} [built]
  [260] ./~/history/lib/useQueries.js 5.91 kB {0} [built]
  [261] ./~/history/~/query-string/index.js 1.48 kB {0} [built]
  [262] ./~/strict-uri-encode/index.js 182 bytes {0} [built]
  [263] ./~/react-router/lib/computeChangedRoutes.js 1.69 kB {0} [built]
  [264] ./~/react-router/lib/TransitionUtils.js 1.89 kB {0} [built]
  [265] ./~/react-router/lib/AsyncUtils.js 1.06 kB {0} [built]
  [266] ./~/react-router/lib/isActive.js 3.11 kB {0} [built]
  [267] ./~/react-router/lib/getComponents.js 971 bytes {0} [built]
  [268] ./~/react-router/lib/matchRoutes.js 6.1 kB {0} [built]
  [269] ./~/react-router/lib/PropTypes.js 1.32 kB {0} [built]
  [270] ./~/react-router/lib/Link.js 5.13 kB {0} [built]
  [271] ./~/react-router/lib/IndexLink.js 1.74 kB {0} [built]
  [272] ./~/react-router/lib/IndexRedirect.js 2.59 kB {0} [built]
  [273] ./~/react-router/lib/Redirect.js 3.5 kB {0} [built]
  [274] ./~/react-router/lib/IndexRoute.js 2.48 kB {0} [built]
  [275] ./~/react-router/lib/Route.js 2.46 kB {0} [built]
  [276] ./~/react-router/lib/History.js 404 bytes {0} [built]
  [277] ./~/react-router/lib/Lifecycle.js 2.4 kB {0} [built]
  [278] ./~/react-router/lib/RouteContext.js 807 bytes {0} [built]
  [279] ./~/react-router/lib/match.js 2.32 kB {0} [built]
  [280] ./~/history/lib/createMemoryHistory.js 4.34 kB {0} [built]
  [281] ./~/history/lib/useBasename.js 4.54 kB {0} [built]
  [282] ./src/js/pages/Archives.js 3.19 kB {0} [built]
  [283] ./src/js/components/Article.js 2.88 kB {0} [built]
  [284] ./src/js/pages/Featured.js 3.43 kB {0} [built]
  [285] ./src/js/pages/Layout.js 3.3 kB {0} [built]
  [286] ./src/js/components/layout/Footer.js 2.61 kB {0} [built]
  [287] ./src/js/components/layout/Nav.js 5.06 kB {0} [built]
  [288] ./src/js/pages/Settings.js 2.32 kB {0} [built]
webpack: Compiled successfully.
View Code

 

 

期待的 UI 效果

Ref: https://github.com/learncodeacademy/react-js-tutorials/tree/master/2-react-router

 

 

一段 navigation 的代码

import { browserHistory, hashHistory, Router, Route, IndexRoute } from 'react-router'
import {Provider} from 'react-redux' render(
<Provider store ={store}> <div> <Router history = { browserHistory }>
// 用 <Route> 来渲染 <Router> <Route path = '/' component= {App} > <IndexRoute component= {Layout} onEnter = {(nextState,replace)=>handleEnter(nextState,replace)}/> <Route path = '/login' component= {Login}/> <Route path = '/signup' component= {SignUp}/> </Route> </Router> </div> </Provider> , document.getElementById('app') )

 

  component 改为了 element。

 

1) 'react-redux' 的 Provider

Ref: react-redux中的Provider组件 [有demo]

 

在 [React] 13 - Redux: react-redux 中有提到。

 

2) 'react-router' 的 browserHistory, hashHistory, Router, Route, IndexRoute 

React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件

所以,过去讲到的原始方式就没必要了:

RR4 本次采用单代码仓库模型架构(monorepo),这意味者这个仓库里面有若干相互独立的包,分别是:

    • react-router           # React Router 核心
    • react-router-dom              # 用于 DOM 绑定 的 React Router
    • react-router-native       # 用于 React Native 的 React Router
    • react-router-redux         # React Router 和 Redux 的集成
    • react-router-config       # 静态路由配置的小助手

关于路由的系统学习:

 

 

 

 

- 再 - 学 - 习 -


Ref: React.js 中文开发入门教学 - 使用路由组件 Router [v5.2.1]

基本的路由例子

手动修改URL,测试路由效果~

  • index.js

import { BrowserRouter } from 'react-router-dom'

ReactDOM.render(
    <React.StrictMode>
        <BrowserRouter>
            <App />
        </BrowserRouter>
    </React.StrictMode>,
    document.getElementById('root')
);

 

  HashRouter 是“弟弟” of BrowserRouter。

 

  • App.js

import Header from './components/Header';

import { Route } from 'react-router-dom';

import PageHome from './components/PageHome';
import PageAbout from './components/PageAbout';
import PageNews from './components/PageNews';

function App() {
    return (
        <div>
            <Header></Header>
            <div className="p-4">
                <Route path="/" exact>
                    <PageHome></PageHome>
                </Route>
                <Route path="/news">
                    <PageNews></PageNews>
                </Route>
                <Route path="/about">
                    <PageAbout></PageAbout>
                </Route>
            </div>
        </div>
    );
}

export default App;

 

  导航栏组件 --> App.js --> PageNewsDetail.js

 

1. 那么导航栏,即可支持带有参数的NavLink。(导航栏是“发起点”)

<NavLink to="/news-detail/103" className="p-2">News3</NavLink>

 

2. Route path format 定义:有参数id,如下:

// App.js
<Route path="/news-detail/:id"> <PageNewsDetail></PageNewsDetail> </Route>

 

3. 通过route过来,提取其中的“参数”。

// /components/PageNewsDetail.js

import React from 'react'; import { useParams } from 'react-router-dom' const PageNewsDetail = () => { const params = useParams(); console.log(params) return (
<div> <h1>PageNewsDetail</h1> <h2>id: {params.id}</h2> <hr /> <pre> {JSON.stringify(params, null, 4)} </pre> </div> ) } export default PageNewsDetail;

 

 

导航栏

点击后,自动跳转到制定的URL。所以,头部组件添加导航link ~

  • /components/Header.js

import React from 'react';
import './Header.css';

import { NavLink } from 'react-router-dom'

const Header = () => {
    return (
        <div className="navbar bg-header p-2 shadow d-flex justify-content-between">
            <div className="text-light">
                <i className="bi bi-life-preserver"></i>
                <span className="fs-5 ps-2">React.js</span>
            </div>
            <div>
                <NavLink to="/"      className="text-decoration-none px-1 text-secondary" activeClassName="text-light" exact>Home</NavLink>
                <NavLink to="/news"  className="text-decoration-none px-1 text-secondary" activeClassName="text-light">News</NavLink>
                <NavLink to="/about" className="text-decoration-none px-1 text-secondary" activeClassName="text-light">About</NavLink>
            </div>
        </div>
    )
}

export default Header;

 

  Nav 的导航栏 会有“高亮” 效果。

 

如果要实现”自定义类名”,className里面需要写成 ”函数“。把函数单独定义出来,这里只是调用,会更优雅一些。

 

 

Nested Routes

这个例子有点水。看样子,只是“子组件”中,而非“父组件”中,定义了Route罢了~

import React from 'react';

import { Route, NavLink } from 'react-router-dom'

const PageAbout = () => {
    return (
        <div>
            <h1>PageAbout</h1>
            <NavLink to="/about/komavideo" exact>详细页面</NavLink>   // 已经在当前的url下的页面~,点击后跳转。
            <hr />
            <Route path="/about/komavideo">               // 跳转到这个url下的页面。
                <h2 className="text-success">小马技术视频</h2>
            </Route>
        </div>
    )
}

export default PageAbout;

 

  以下是嵌套路由的UI展示。

 

    • 创建 News.jsx and Message.jsx, 然后再重构下 路由表 以及 Home.jsx

Message.jsx 中添加如上图一般的 “超链接”。

News.jsx 只是简单的添加如下。<li> 表示:用于表示列表里的条目

 

    •  然后,1) 增加 children 于路由表

./routes/index.js

import Home from '../pages/Home'
import Message from '../pages/Message'
import News from '../pages/News'

export default [   {     path: '/about',     element:<About/>   },   {     path: '/home',     element:<Home/>,     children: [       {         path: 'news',         element: <News/>       },       {         path: 'message',         element: <Message/>       }     ]   },   {     path: '/',     element: <Navigate to="/about"/>   } ]

 

    • 然后,2) refactor Home.jsx

NavLink指向的组件的内容会显示在 <Outlet />部分。

 

在上图 linn4-5之间可以加上如下。该方法,用来呈现当前组件中所渲染的嵌套路由。 

console.log('###', useOutline())

 

 

  路由的 param 参数 by useParams()

针对提取参数,引入:最新版本的路由param参数,这里直接是个三级目录的嵌套路由的例子。 

'children' 嵌套如下。

routes/index.js

  {     path:
'/home',     element:<Home/>,     children: [       {         path: 'news',         element: <News/>       },       {         path: 'message',         element: <Message/>
children:[
{
path:'detail/:id/:title/:content', # 因为detail是内容丰富的,所以这里的url自然会丰富许多
element:<Detail/>
}
]      }     ]   },

 

Message.jsx 中 大换血。需要增加detail.js文件。

url: /home/message/detail

此时点击 "消息1“,下面会显示组件的内容,但注意:url 却不变。

下一步,我们希望 给下面 “传参” by url。

./Message.jsx

return
{ <div> <ul> { message.map( (m)=>{ return ( // 路由链接 <li key={m.id}> <Link to={`detail/$(m.id)/$(m.title)/$(m.content)`}>{m.title}</Link> # 点击这个 title,跳转到这个链接,该链接对应的组件在上面route定义,遂展示detail内容。 </li> ) }) } </ul> <hr /> {/* 指定路由组件的展示位置 */} <Outlet /> </div> ) }

 

以下是 detail.jsx组件 的实现 by useParams()。

过去“类组件”时的:history, match, location之类,现在变成怎样了呢 in 函数组件? 如上,useMatch能用(line6),但没有必要。line5的形式就挺好!

 

 

  search 参数 (另一种形式的url 参数定义)

(1)更新 routes/index.jsx,如下不再需要detail后面的东西。(如 state 参数的)

(2)主要url中参数格式的变化。

./Message.jsx

return {
    <div>
        <ul>
            {
                message.map( (m)=>{
                    return (
                        // 路由链接
                        <li key={m.id}>
                            <Link to=`detail?id=${m.id}&title=${m.title}&content=${m.content}`}>{m.title}</Link>
                        </li>
                    )
                })
             }
        </ul>
        <hr />
        {/* 指定路由组件的展示位置 */}
        <Outlet />
        </div>
    )
}

 

(3)Detail.jsx如下,通过 useSearchParams() 获得url中的各个参数。如下示范,通过点击一个按钮,改变url(其中自带参数),重新render后,自然就改变了Detail组件的内容。

 

 

  state 参数

(1)更新 routes/index.jsx,如下不再需要detail后面的东西。

 path:'detail/:id/:title/:content',  # 因为detail是内容丰富的,所以这里的url自然会丰富许多

path:'detail',

 

(2)更新 Message.jsx,给组件传参采用新的format,请见 link to。

./Message.jsx

return {
    <div>
        <ul>
            {
                message.map( (m)=>{
                    return (
                        // 路由链接
                        <li key={m.id}>
                            <Link 
to="detail"
state={{
id:m.id,
title:m.title,
content:m.content,
}}
>{m.title}</Link>
</li> ) }) } </ul> <hr /> {/* 指定路由组件的展示位置 */} <Outlet /> </div> ) }

 

(3)Detail.jsx如 下,通过 useLocation() 获得state中的各个参数。

  

 

  useResolvedPath()

  给定一个 URL值,解析其中的:path, search, hash值。

 

useResolvedPath('/user?id=001&name=tom#qwe)

 

 

路由重定向

无效路径,自然需要redirect to an available web page (URL).

import { Route, Switch, Redirect } from 'react-router-dom';
...
    // <Route path="/" exact>
    //     <PageHome></PageHome>
    // </Route>
...
    <Route path="/" exact>
        <Redirect to="/home"></Redirect>
    </Route>
    <Route path="/home">
        <PageHome></PageHome>
    </Route>
...

 

    • 404 处理

找不到,则导入默认的一个 "404组件"。

import NotFound from './pages/NotFound';
...
    <Switch>
...
        <Route path="*">
            <NotFound></NotFound>
        </Route>
    </Switch>
...

"404组件" 定义如下。

import React from 'react';

const NotFound = () => {
    return (
        <h1>404:NotFound</h1>
    )
}

export default NotFound;

 

  switch 改为 routes 即可。

 

Navigate 只要 ”被渲染“,就会“跳转“。

例如,鼠标划过某个带有链接能力的图片,但其实不应该触发这个链接,所以navigate在这里就不合适。

如果加上 replace, 重定向后的页面 就无法通过”浏览器回退“ 返回,因为被替换掉了~

<Navigate to="/about" replace={true}/> 

 

 

路由表 - useRoutes

  越来越像vue,以及django传统的路由定义方式。

 

import routes from "./routes"

const element = useRoutes(routes)

以下是上面的 蓝色的 const element。

<div className="panel-body">
  {element}
</div>

 

 

编程路由 - useHistory

这里的例子,通过onClick来体现“编程的方式”。

/pages/Login.js

import React from 'react';

const Login = () => {
    return (
        <h1>Login</h1>
    )
}

export default Login;
View Code

 

push 方法有 goto url的效果。通过点击按钮,在onClick函数中 定义“链接跳转” 的效果。

import React from 'react';
import './Header.css';
import { NavLink, useHistory } from 'react-router-dom'

const Header = (props) => {
// 新增代码 const history = useHistory(); const btn_login_click = () => { history.push("/login") } const btn_logout_click = () => { history.push("/") }
return (
<div className="navbar bg-header p-2 shadow d-flex justify-content-between"> <div className="text-light"> <i className="bi bi-life-preserver"></i> {/*新增代码*/} <NavLink className="fs-5 ps-2 link-light text-decoration-none" to="/">React.js</NavLink> </div> <div> {/*新增代码*/} <button className="btn btn-primary btn-sm mx-1" onClick={btn_login_click}>登陆</button> // --> 通过onClick函数中的push达到了 NavLinkto的效果 <button className="btn btn-danger btn-sm mx-1" onClick={btn_logout_click}>退出</button> </div> </div> ) } export default Header;

 

  Ref: 编程式路由导航

  通过点击按钮达到跳转的效果,有点类似上面的push 例子。但这里的v6又出现了什么新意了么?

 

若在 ./index.js 下将某个组件 放置在 </BrowserRouter> 外,就可以不受路由体系的范围控制。

./pages/Message.jsx

import React, {useState} from 'react'; import { Link, Outlet, useNavigate, useInRouterContext } from 'react-router-dom' export default function Message() { const navigate = useNavigate()

console.log("***", useInRouterContext())  # <---判断是否在路由体系下的控制范围之内 True or False

const [message] = useState([
...
])
// 点击按钮后,触发该函数中,通过 navigate 进入相对的url path. function showDetail_onClick(m) {     navigate('detail', {
replace: false,
state: {
id:m.id,
title:m.title,
content:m.content
}
})
} }

如下 ./components/header/index.jsx,简单的 -1, 1就可以实现前后历史浏览进退,貌似更为简单。

 

  useNavigationType()

  返回当前的导航类型(用户是如何来到当前页面的)

  POP, PUSH, REPLACE

 

const result = useOutlet()
console.log(result)

 

 

页面跳转传参 - useLocation

那上个页面跳转过来时,顺便传过来几个参数。

/components/Header.js

    const btn_login_click = () => {
        // 传入登陆页面2个参数:name, password
        history.push("/login?name=koma&password=12345678")
    }

/pages/Login.js

import React from 'react';
import { useLocation } from 'react-router-dom'

const Login = () => {
    const location = useLocation();
    const urlParams = new URLSearchParams(location.search);

    console.log(urlParams.toString());

    return (
        <React.Fragment>
            <h1>Login</h1>
            <hr />
            <div className="fs-2">
                Name: <span className="badge bg-primary">{urlParams.get("name")}</span>
            </div>
            <div className="fs-2">
                Password: <span className="badge bg-secondary">{urlParams.get("password")}</span>
            </div>
        </React.Fragment>
    )
}

export default Login;

 

 

 

 

ReactRouter v6 (draft)


Ref: 2022针对 ReactRouter6 加更章节:p127-141 [v6]

Ref: 总结变化

函数组件将成为未来趋势!

 

react-router

react-router-dom

react-router-native

 

移除了 <Switch/> 新增 <Routes/>

component = {About} 变为 element = {About}

新增多个 hook: useParams, useNavigate, useMatch等。(类组件中不能使用Hook的,所以官方u推荐“函数组件”)

 

posted @ 2018-05-10 18:50  郝壹贰叁  阅读(331)  评论(0编辑  收藏  举报