Ref: REACT JS TUTORIAL #6 - React Router & Intro to Single Page Apps with React JS css
Ref: REACT JS TUTORIAL #7 - React Router Params & Querieshtml
Ref: REACT JS TUTORIAL #8 - React Inline Styles & Component Arraysnode
Ref: react 技巧 #3 react-router 教程 part 1react
Ref: react 技巧 #4 react-router 教程 part 2android
webpack
参考:npm使用教程git
安装方法总结github
==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 这个里面。web
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"
}
lolo@lolo-UX303UB$ npm run devajax
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.
Ref: https://github.com/learncodeacademy/react-js-tutorials/tree/master/2-react-router
Figure 01
React-router是个插件,源码:
* https://github.com/ReactTraining/react-router【库源码】
* https://reacttraining.com/react-router/web/example/basic【API使用示范】
# 须要导入的今天主角儿
import { BrowserRouter as Router, Route } from 'react-router-dom'
Figure, typical navigation bar for implementing router
App.js
import React, { Component } from 'react'; import './App.css'; import Home from './pages/Home'; import { BrowserRouter as Router, Route } from 'react-router-dom' import About from './pages/About.js'; import Contact from './pages/Contact.js';
// 公用的三个组件 import Navbar from './components/Navbar'; import Jumbotron from './components/Jumbotron'; import Footer from './components/Footer'; class App extends Component { render() { return (
<Router> <div> <Navbar />
<Jumbotron title="Welcome" subtitle="Put something witty here!" />
/**
* http://localhost:3000/contact
* 不一样的url加载不一样的组件,对应相应的页面,以下图figure 02.
*/ <Route exact path="/" component={Home} /> // 这里若没有exact会出现奇怪的页面 <Route path="/contact" component={Contact} /> <Route path="/about" component={About} />
<Footer /> </div> </Router> ); } } export default App;
Figure 02
<div className="collapse navbar-collapse" id="navbarCollapse"> <ul className="navbar-nav ml-auto">
-------------------------------------------------------------------------------------------- <li className="nav-item active"> <LinkclassName="nav-link" to="/">Home <span className="sr-only">(current)</span></Link> </li>
-------------------------------------------------------------------------------------------- <li className="nav-item"> <LinkclassName="nav-link" to="/about">About</Link> </li>
-------------------------------------------------------------------------------------------- <li className="nav-item"> <LinkclassName="nav-link" to="/contact">Contact</Link> </li>
-------------------------------------------------------------------------------------------- </ul> </div>
支持”带井号“的 url: http://localhost:3000/#/contact
import {
HashRouter as Router,
Route
} from 'react-router-dom'
三个页面不必写三次NavBar的代码
以下所示 代码"共用部分" 可转移至App.js中。
class About extends Component { render() { return (
<div>
---------------------------------------------------
此部分可转移到app.js中
---------------------------------------------------
<Navbar />
<Jumbotron title="About Me!" subtitle=...
--------------------------------------------------- <div className="container"> <h2>About</h2> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc placerat orci eu nulla sagittis, pulvinar dignissim lectus consequat. Etiam in lobortis ligula, vitae ornare lacus. Vivamus scelerisque lorem arcu, vitae eleifend ex commodo a. Quisque rutrum, augue sit amet egestas efficitur, magna nulla lacinia elit, sed suscipit tortor erat vitae enim. Donec egestas odio id aliquet rhoncus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Quisque mi dolor, egestas nec lacinia non, sodales eu lacus. Donec ultricies nec elit ac ornare. Quisque fermentum ligula ut feugiat cursus. Aliquam auctor suscipit ex a lacinia. Mauris sollicitudin, justo quis fringilla finibus, dui diam ullamcorper nulla, sit amet placerat justo neque quis quam. Praesent nec nibh at tortor ornare dignissim. Morbi tincidunt fringilla turpis at luctus. Vivamus dapibus ligula eget pellentesque luctus. Maecenas ut consectetur lacus, non dignissim nisi. Praesent sodales tellus sit amet faucibus tempus. </p> <p> Maecenas dapibus, est posuere eleifend rutrum, lectus ligula gravida urna, at pretium dui turpis non lorem. Donec pretium lorem ipsum, at fermentum nibh consequat facilisis. Sed maximus massa est, vel porta diam placerat id. Vivamus imperdiet lorem eget dolor bibendum, eget gravida tellus interdum. Sed lectus odio, condimentum eu porttitor vel, euismod sit amet urna. Nam quis dui a nibh rhoncus aliquam vitae in metus. Nam sit amet semper turpis. Suspendisse eu malesuada tortor, vel lacinia nisl. Phasellus ultrices vehicula magna, sed tempor neque dapibus quis. Phasellus urna justo, sollicitudin ac odio eget, convallis varius nulla. Vivamus in lacinia lorem, at eleifend nulla. Nulla nec luctus purus. Integer id purus mauris. Phasellus finibus ultricies erat a tempus. Nulla luctus sem nec justo venenatis, eu faucibus purus congue. </p> </div> </div>
); } }
在"about页面"下的
在标题下加一个按钮,点击后跳转到首页!
触发函数 onNavigateHome 在bind后到底会新增什么操做权限?
<button onClike={this.onNavigateHome.bind(this)} className="btn btn-primar">Go Home!</button>
onNavigateHome中的 this.props 附带了以下:
Ref: https://reacttraining.com/react-router/web/api/history【官方文档】
history.push(...) 能重写URL.
history.replaceState // 不记录回退
history.pushState // 记录回退
以下形式岂不是更简单、好用。
<Link className="navbar-brand" to="/">React Website</Link>
Router
组件有一个参数history
,它的值hashHistory
表示,路由的切换由URL的hash变化决定,即URL的#
部分发生变化。
举例来讲,用户访问http://www.example.com/
,实际会看到的是http://www.example.com/#/
。
<Router history={hashHistory}> <Route path="/" component={App}/> <Route path="/repos" component={Repos}/> <Route path="/about" component={About}/> </Router>
用户访问一个路由,会自动跳转到另外一个路由。
<Route path="inbox" component={Inbox}> {/* 从 /inbox/messages/:id 跳转到 /messages/:id */} <Redirect from="messages/:id" to="/messages/:id" /> </Route>
如今访问/inbox/messages/5
,会自动跳转到/messages/5
。
IndexRedirect
组件用于访问根路由的时候,将用户重定向到某个子组件。
<Route path="/" component={App}> <IndexRedirect to="/welcome" /> <Route path="welcome" component={Welcome} /> <Route path="about" component={About} /> </Route>
上面代码中,用户访问根路径时,将自动重定向到子组件welcome
。
IndexLink
组件若是连接到根路由/
,不要使用Link
组件,而要使用IndexLink
组件。
理由:由于/
会匹配任何子路由;对于根路由来讲,activeStyle
和activeClassName
会失效,或者说老是生效。
方案:IndexLink
组件会使用路径的精确匹配。
<IndexLinkto="/" activeClassName="active"> Home </IndexLink>
方案:或者使用 onlyActiveOnIndex 属性
<Link to="/" activeClassName="active"onlyActiveOnIndex={true}> Home </Link>
在Router
组件以外,导航到路由页面,可使用浏览器的History API。
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
监听浏览器地址栏的变化 ---> 将URL解析成一个地址对象 ---> 供 React Router 匹配。
(1) 路由将经过URL的hash部分(#
)切换,URL的形式相似example.com/#/some/path
import { hashHistory } from 'react-router' render( <Router history={hashHistory} routes={routes} />, document.getElementById('app') )
(2) 浏览器的路由就显示正常的路径example.com/some/path
,背后调用的是浏览器的History API。
import { browserHistory } from 'react-router' render( <Router history={browserHistory} routes={routes} />, document.getElementById('app') )
可是,这种状况须要对服务器改造。不然用户直接向服务器请求某个子路由,会显示网页找不到的404错误。
若是开发服务器使用的是webpack-dev-server
,加上--history-api-fallback
参数就能够了。
$ webpack-dev-server --inline --content-base . --history-api-fallback
(3).createMemoryHistory
主要用于服务器渲染。它建立一个内存中的history
对象,不与浏览器URL互动。
const history = createMemoryHistory(location)
class App extends Component { render() { return ( <Router> <div> <Navbar /> <Jumbotron title="Welcome" subtitle="Put something witty here!" /> /** * http://localhost:3000/contact * 不一样的url加载不一样的组件,对应相应的页面,如上图figure 01. */ <Route exact path="/" component={Home} /> // 这里若没有exact会出现奇怪的页面 <Route path="/contact/:id" component={Contact} /> <Route path="/about" component={About} /> <Footer /> </div> </Router> ); } }
import React, { Component } from 'react'; class About extends Component { render() {
console.log(this.props);
return ( <div> <div className="container"> <h2>Contact {this.props.match.params.id}</h2> // 这里又是this,又是props,是否是感受很啰嗦?!须要经过无状态组件来改善
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc placerat orci eu nulla sagittis, pulvinar dignissim lectus consequat. Etiam in lobortis ligula, vitae ornare lacus. Vivamus scelerisque lorem arcu, vitae eleifend ex commodo a. Quisque rutrum, augue sit amet egestas efficitur, magna nulla lacinia elit, sed suscipit tortor erat vitae enim. Donec egestas odio id aliquet rhoncus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Quisque mi dolor, egestas nec lacinia non, sodales eu lacus. Donec ultricies nec elit ac ornare. Quisque fermentum ligula ut feugiat cursus. Aliquam auctor suscipit ex a lacinia. Mauris sollicitudin, justo quis fringilla finibus, dui diam ullamcorper nulla, sit amet placerat justo neque quis quam. Praesent nec nibh at tortor ornare dignissim. Morbi tincidunt fringilla turpis at luctus. Vivamus dapibus ligula eget pellentesque luctus. Maecenas ut consectetur lacus, non dignissim nisi. Praesent sodales tellus sit amet faucibus tempus. </p> <p> Maecenas dapibus, est posuere eleifend rutrum, lectus ligula gravida urna, at pretium dui turpis non lorem. Donec pretium lorem ipsum, at fermentum nibh consequat facilisis. Sed maximus massa est, vel porta diam placerat id. Vivamus imperdiet lorem eget dolor bibendum, eget gravida tellus interdum. Sed lectus odio, condimentum eu porttitor vel, euismod sit amet urna. Nam quis dui a nibh rhoncus aliquam vitae in metus. Nam sit amet semper turpis. Suspendisse eu malesuada tortor, vel lacinia nisl. Phasellus ultrices vehicula magna, sed tempor neque dapibus quis. Phasellus urna justo, sollicitudin ac odio eget, convallis varius nulla. Vivamus in lacinia lorem, at eleifend nulla. Nulla nec luctus purus. Integer id purus mauris. Phasellus finibus ultricies erat a tempus. Nulla luctus sem nec justo venenatis, eu faucibus purus congue. </p> </div> </div> ); } } export default About
原始写法,采用了 class About extends Component 类的这种啰嗦形式。
而且,要反复写 this.props 这一部分。
可见,类的形式是没有必要的;函数形式就能够了。
如此,就能够省略掉this.props 这部分。
根本缘由:箭头函数对于this有更好的效果!
(1) 第一步精简,保留了props。
(2) 进一步精简,只使用match。
const About = ({ match }) => { render() { console.log(this.props); return ( <div> <div className="container"> <h2>Contact {match.params.id}</h2> // 这里又是this,又是props,是否是感受很啰嗦?!须要经过无状态组件来改善
(3) 补充:使用箭头函数,就能够不使用 this.increment.bind(this) 写法。
Ref: http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu
<Route path="/hello/:name"> // 匹配 /hello/michael // 匹配 /hello/ryan <Route path="/hello(/:name)"> // 匹配 /hello // 匹配 /hello/michael // 匹配 /hello/ryan <Route path="/files/*.*"> // 匹配 /files/hello.jpg // 匹配 /files/hello.html <Route path="/files/*"> // 匹配 /files/ // 匹配 /files/a // 匹配 /files/a/b <Route path="/**/*.jpg"> // 匹配 /files/hello.jpg // 匹配 /files/path/to/file.jpg
注意:带参数的路径通常要写在路由规则的底部。
<Router> <Route path="/:userName/:id" component={UserPage}/> <Route path="/about/me" component={About}/> </Router>
React Router Params & Queries
Ref: URL中“#” “?” &“”号的做用【有机会能够深刻理解下】
import React from "react"; import Article from "../components/Article"; export default class Archives extends React.Component { render() { const { query } = this.props.location; // <---- const { params } = this.props; // <----
const { date, filter } = query; const { article } = params;
const Articles = [ "Some Article", "Some Other Article", "Yet Another Article", "Still More", "Fake Article", "Partial Article", "American Article", "Mexican Article", ].map((title, i) => <Article key={i} title={title}/> ); return ( <div> <h1>Archives</h1> article: {article}, date: {date}, filter: {filter} <div class="row">{Articles}</div> </div> ); } }
[需查代码,看效果]
关键在于粉色部分会被提取出来。
http://localhost:8080/#/archives/article_12?_k=94cbzi
提取效果:
http://localhost:8080/#/archives/article_12?date=today&filter=none&_k=kv6hs4
提取效果:
由于plugins:react-html-attrs,因此能够直接使用class,而不是屈就于className。
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : null,
entry: "./js/client.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy'], <---- 加上这个插件便可
}
}
]
},
output: {
path: __dirname + "/src/",
filename: "client.min.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
};
以下:直接使用了class关键字。
render() { const { location } = this.props; const { collapsed } = this.state; const featuredClass = location.pathname === "/" ? "active" : ""; const archivesClass = location.pathname.match(/^\/archives/) ? "active" : ""; const settingsClass = location.pathname.match(/^\/settings/) ? "active" : ""; const navClass = collapsed ? "collapse" : ""; return ( <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" onClick={this.toggleCollapse.bind(this)} > <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <div class={"navbar-collapse " + navClass} id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class={featuredClass}> <IndexLink to="/" onClick={this.toggleCollapse.bind(this)}>Featured</IndexLink> </li> <li class={archivesClass}> <Link to="archives" onClick={this.toggleCollapse.bind(this)}>Archives</Link> </li> <li class={settingsClass}> <Link to="settings" onClick={this.toggleCollapse.bind(this)}>Settings</Link> </li> </ul> </div> </div> </nav> ); }
import React from "react"; import Article from "../components/Article"; export default class Featured extends React.Component {
render() {
const Articles = [ "Some Article", "Some Other Article", "Yet Another Article", "Still More", "Some Article", "Some Other Article", "Yet Another Article", "Still More", "Some Article", "Some Other Article", "Yet Another Article", "Still More", ].map((title, i) => <Article key={i} title={title}/> ); const adText = [ "Ad spot #1", "Ad spot #2", "Ad spot #3", "Ad spot #4", "Ad spot #5", ]; const randomAd = adText[Math.round( Math.random() * (adText.length-1) )]; console.log("featured"); return ( <div> <div class="row"> <div class="col-lg-12"> <div class="well text-center"> {randomAd} </div> </div> </div> <div class="row">{Articles}</div> </div> ); }
import React from "react"; import ReactDOM from "react-dom"; import { Router, Route, IndexRoute, hashHistory } from "react-router"; import Archives from "./pages/Archives"; import Featured from "./pages/Featured"; import Layout from "./pages/Layout"; import Settings from "./pages/Settings"; const app = document.getElementById('app'); ReactDOM.render( <Router history={hashHistory}> <Route path="/" component={Layout}> <IndexRoute component={Featured}></IndexRoute> <Route path="archives(/:article)" name="archives" component={Archives}></Route> <Route path="settings" name="settings" component={Settings}></Route> </Route> </Router>, app);
[重难点] 一个不错的控件,能够直接使用
import React from "react"; import { IndexLink, Link } from "react-router"; export default class Nav extends React.Component { constructor() { super() this.state = { collapsed: true, }; } toggleCollapse() { const collapsed = !this.state.collapsed; this.setState({collapsed}); } render() { const { location } = this.props; const { collapsed } = this.state; // tab是否有激活效果(被摁下的效果),这里是经过url来判断 const featuredClass = location.pathname === "/" ? "active" : ""; const archivesClass = location.pathname.match(/^\/archives/) ? "active" : ""; const settingsClass = location.pathname.match(/^\/settings/) ? "active" : "";
// 控制“下拉菜单"的效果 const navClass = collapsed ? "collapse" : ""; return ( <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" onClick={this.toggleCollapse.bind(this)} > <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <div class={"navbar-collapse " + navClass} id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class={featuredClass}> <IndexLink to="/" onClick={this.toggleCollapse.bind(this)}>Featured</IndexLink> </li> <li class={archivesClass}> <Link to="archives" onClick={this.toggleCollapse.bind(this)}>Archives</Link> </li> <li class={settingsClass}> <Link to="settings" onClick={this.toggleCollapse.bind(this)}>Settings</Link> </li> </ul> </div> </div> </nav> ); } }
一段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') )
Ref: react-redux中的Provider组件 [有demo]
在 [React] 13 - Redux: react-redux 中有提到。
React Router4是一个流行的纯React重写的包。如今的版本中已不须要路由配置,如今一切皆组件。
因此,过去讲到的原始方式就不必了:
[React] 05 - Route: connect with ExpressJS
[React] 06 - Route: koa makes your life easier
RR4 本次采用单代码仓库模型架构(monorepo),这意味者这个仓库里面有若干相互独立的包,分别是:
react-router
# React Router 核心react-router-dom
# 用于 DOM 绑定的 React Routerreact-router-native
# 用于 React Native 的 React Routerreact-router-redux
# React Router 和 Redux 的集成react-router-config
# 静态路由配置的小助手
关于路由的系统学习:
Ref: React Router 4 简易入门
Ref: React学习教程(7)React-Router简介&安装
Ref: React Router 中文文档 [不错]