{"id":17987358,"url":"https://github.com/dog-days/react-router-controller","last_synced_at":"2026-05-19T06:02:09.858Z","repository":{"id":57343744,"uuid":"99665352","full_name":"dog-days/react-router-controller","owner":"dog-days","description":"react-router-controller，react路由控制器","archived":false,"fork":false,"pushed_at":"2017-12-04T06:27:56.000Z","size":218,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-26T03:06:34.088Z","etag":null,"topics":["controllers","react-router-controller","yii"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dog-days.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-08-08T07:47:00.000Z","updated_at":"2017-08-12T07:37:48.000Z","dependencies_parsed_at":"2022-09-12T06:51:02.394Z","dependency_job_id":null,"html_url":"https://github.com/dog-days/react-router-controller","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dog-days/react-router-controller","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dog-days%2Freact-router-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dog-days%2Freact-router-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dog-days%2Freact-router-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dog-days%2Freact-router-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dog-days","download_url":"https://codeload.github.com/dog-days/react-router-controller/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dog-days%2Freact-router-controller/sbom","scorecard":{"id":349642,"data":{"date":"2025-08-11","repo":{"name":"github.com/dog-days/react-router-controller","commit":"73c1c12ea69c7054c1eb78b2430b1ec1c2292e68"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"164 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-whgm-jr23-g3j9","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-fwr7-v2mv-hh25","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx","Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-x9w5-v3q2-3rhw","Warn: Project is vulnerable to: GHSA-wxhq-pm8v-cw75","Warn: Project is vulnerable to: GHSA-257v-vj4p-3w2h","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-p28h-cc7q-c4fg","Warn: Project is vulnerable to: GHSA-9vvw-cc9w-f27h","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-hr2v-3952-633q","Warn: Project is vulnerable to: GHSA-3wcq-x3mq-6r9p","Warn: Project is vulnerable to: GHSA-ff7x-qrg7-qggm","Warn: Project is vulnerable to: GHSA-vh7m-p724-62c2","Warn: Project is vulnerable to: GHSA-r9p9-mrjm-926w","Warn: Project is vulnerable to: GHSA-434g-2637-qmqr","Warn: Project is vulnerable to: GHSA-49q7-c7j4-3p7m","Warn: Project is vulnerable to: GHSA-977x-g7h5-7qgw","Warn: Project is vulnerable to: GHSA-f7q4-pwc6-w24p","Warn: Project is vulnerable to: GHSA-fc9h-whq2-v747","Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh","Warn: Project is vulnerable to: GHSA-j4f2-536g-r55m","Warn: Project is vulnerable to: GHSA-r7qp-cfhv-p84w","Warn: Project is vulnerable to: GHSA-4gmj-3p3h-gm8h","Warn: Project is vulnerable to: GHSA-6h5x-7c5m-7cr7","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-qrmc-fj45-qfc2","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-mpcf-4gmh-23w8","Warn: Project is vulnerable to: GHSA-9qj9-36jm-prpv","Warn: Project is vulnerable to: GHSA-8r6j-v8pm-fqw3","Warn: Project is vulnerable to: MAL-2023-462","Warn: Project is vulnerable to: GHSA-xf7w-r453-m56c","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-q42p-pg8m-cqh6","Warn: Project is vulnerable to: GHSA-w457-6q6x-cgp9","Warn: Project is vulnerable to: GHSA-62gr-4qp9-h98f","Warn: Project is vulnerable to: GHSA-f52g-6jhx-586p","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-44pw-h2cw-w3vq","Warn: Project is vulnerable to: GHSA-jp4x-w63m-7wgm","Warn: Project is vulnerable to: GHSA-c429-5p7v-vgjp","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-pfq8-rq6v-vf5m","Warn: Project is vulnerable to: GHSA-6x33-pw7p-hmpq","Warn: Project is vulnerable to: GHSA-c7qv-q95q-8v27","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-4hpf-3wq7-5rpr","Warn: Project is vulnerable to: GHSA-f522-ffg8-j8r6","Warn: Project is vulnerable to: GHSA-7r28-3m3f-r2pr","Warn: Project is vulnerable to: GHSA-r8j5-h5cx-65gg","Warn: Project is vulnerable to: GHSA-2pr6-76vf-7546","Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-282f-qqgm-c34q","Warn: Project is vulnerable to: GHSA-76p3-8jx3-jpfq","Warn: Project is vulnerable to: GHSA-3rfm-jhwj-7488","Warn: Project is vulnerable to: GHSA-hhq3-ff78-jv3g","Warn: Project is vulnerable to: GHSA-fvqr-27wr-82fm","Warn: Project is vulnerable to: GHSA-4xc9-xhrj-v574","Warn: Project is vulnerable to: GHSA-x5rq-j2xg-h7qm","Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-pp57-mqmh-44h7","Warn: Project is vulnerable to: GHSA-4xcv-9jjx-gfj3","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-wrvr-8mpx-r7pp","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-w9mr-4mfr-499f","Warn: Project is vulnerable to: GHSA-ff6r-5jwm-8292","Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g","Warn: Project is vulnerable to: GHSA-92xj-mqp7-vmcj","Warn: Project is vulnerable to: GHSA-wxgw-qj99-44c2","Warn: Project is vulnerable to: GHSA-5rrq-pxf6-6jx5","Warn: Project is vulnerable to: GHSA-8fr3-hfg3-gpgp","Warn: Project is vulnerable to: GHSA-gf8q-jrpm-jvxq","Warn: Project is vulnerable to: GHSA-2r2c-g63r-vccr","Warn: Project is vulnerable to: GHSA-cfm4-qjh2-4765","Warn: Project is vulnerable to: GHSA-x4jg-mjrx-434g","Warn: Project is vulnerable to: GHSA-rp65-9cf3-cjxr","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-q75g-2496-mxpp","Warn: Project is vulnerable to: GHSA-6fx8-h7jm-663j","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59","Warn: Project is vulnerable to: GHSA-566m-qj78-rww5","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-hxcm-v35h-mg2x","Warn: Project is vulnerable to: GHSA-6g33-f262-xjp4","Warn: Project is vulnerable to: GHSA-5q6m-3h65-w53x","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6","Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj","Warn: Project is vulnerable to: GHSA-fxwf-4rqh-v8g3","Warn: Project is vulnerable to: GHSA-25hc-qcg6-38wj","Warn: Project is vulnerable to: GHSA-xfhh-g9f5-x4m4","Warn: Project is vulnerable to: GHSA-qm95-pgcg-qqfq","Warn: Project is vulnerable to: GHSA-cqmj-92xf-r6r9","Warn: Project is vulnerable to: GHSA-c9g6-9335-x697","Warn: Project is vulnerable to: GHSA-2m39-62fm-q8r3","Warn: Project is vulnerable to: GHSA-mf6x-7mm4-x2g7","Warn: Project is vulnerable to: GHSA-j44m-qm6p-hp7m","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-g7q5-pjjr-gqvp","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-662x-fhqg-9p8v","Warn: Project is vulnerable to: GHSA-394c-5j6w-4xmx","Warn: Project is vulnerable to: GHSA-78cj-fxph-m83p","Warn: Project is vulnerable to: GHSA-fhg7-m89q-25r3","Warn: Project is vulnerable to: GHSA-pv4c-p2j5-38j4","Warn: Project is vulnerable to: GHSA-46c4-8wrp-j99v","Warn: Project is vulnerable to: GHSA-9m6j-fcg5-2442","Warn: Project is vulnerable to: GHSA-hh27-ffr2-f2jc","Warn: Project is vulnerable to: GHSA-rqff-837h-mm52","Warn: Project is vulnerable to: GHSA-8v38-pw62-9cw2","Warn: Project is vulnerable to: GHSA-hgjh-723h-mx2j","Warn: Project is vulnerable to: GHSA-jf5r-8hm2-f872","Warn: Project is vulnerable to: GHSA-wr3j-pwj9-hqq6","Warn: Project is vulnerable to: GHSA-cf66-xwfp-gvc4","Warn: Project is vulnerable to: GHSA-4v9v-hfq4-rm2v","Warn: Project is vulnerable to: GHSA-9jgg-88mc-972h","Warn: Project is vulnerable to: GHSA-g78m-2chm-r7qv","Warn: Project is vulnerable to: GHSA-5v72-xg48-5rpm","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-3x9f-74h4-2fqr","Warn: Project is vulnerable to: GHSA-8vcr-vxm8-293m","Warn: Project is vulnerable to: GHSA-g973-978j-2c3p","Warn: Project is vulnerable to: GHSA-4r6h-8v6p-xvw6","Warn: Project is vulnerable to: GHSA-5pgg-2g8v-p4x9","Warn: Project is vulnerable to: GHSA-72mh-269x-7mh5","Warn: Project is vulnerable to: GHSA-h4j5-c7cj-74xg","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T08:01:47.955Z","repository_id":57343744,"created_at":"2025-08-18T08:01:47.956Z","updated_at":"2025-08-18T08:01:47.956Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33203999,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T09:27:30.708Z","status":"online","status_checked_at":"2026-05-19T02:00:06.763Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["controllers","react-router-controller","yii"],"created_at":"2024-10-29T19:08:36.406Z","updated_at":"2026-05-19T06:02:09.832Z","avatar_url":"https://github.com/dog-days.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Router Controller\n\n[![npm package](https://badge.fury.io/js/react-router-controller.svg)](https://www.npmjs.org/package/react-router-controller) [![NPM downloads](http://img.shields.io/npm/dm/react-router-controller.svg)](https://npmjs.org/package/react-router-controller)\n\nreact-router-controller启发于[PHP Yii框架](http://www.yiichina.com/doc/guide/2.0)，实现了根据url动态渲染页面（这得益于react-router@4.x.x实现的动态路由）。\n\n\u003e **建议配合webpack使用**\n\n\u003e 这个路由从始至终都只运行了一个路由配置，因为这个路由是动态的，不存在同时存在其他路由配置。\n\n## 为什么要使用这个\n\n- 无路由配置\n\n- 后端控制器模式\n\n  react-router-controller是MVC中的VC，React是View，Controller是C，再配合redux或者mobx就是MVC模式了。思路简单明了，专心于业务逻辑即可。\n\n## 缺点\n\n用这个当然会有点限制，不能自定义路由（定义路由需要遵循controller规范，页面内部的多级动态路由不影响，可以随意定，但是不建议使用子路由）。\n\n## 兼容性\n\n一般主流浏览器都兼容。\n\n- chrome浏览器最新版\n\n- 火狐浏览器最新版\n\n- Edge浏览器最新版\n\n- IE浏览器支持IE9版本以上（包括IE9）\n\n  因为IE不支持promise，所以需要引入polyfill.js。\n\n  ```js\n  import 'react-router-controller/libs/polyfill'\n  //如果已经有相关的promise polyfill，可以不用这个。\n  ```\n\n## 使用规范\n\n就像PHP Yii一样（90%相似），react-router-controller也有自己的规范。\n\n### URL规范\n\n跟Yii基本一致，处理没有module这分类。\n\n- controllerId和viewId\n\n  url必须要包括controllerId和viewId（controller名和view名，为了解析成动态路由），例如`http://localhost:8000/main/about`，这个路由会解析成参数传入controller的view函数中（`{conrollerId: main,vieId: about}`）。\n\n- 路由参数\n\n  除开controllerId和viewId外，后面url接的参数也有一定的规则，前面第一个是react-router参数设置名，后面的是参数值（成对出现，理论是可以无限个）。例如url`http://localhost:8000/main/about/id/100/appid/test/page/2`，会解析成params（controller xxxView函数参数、layout组件和view组件的props.params）：\n\n  ```json\n  {\n    controllerId: \"main\",\n    viewId: \"about\",\n    id: \"100\",\n    appid: \"test\",\n    page: \"2\"\n  }\n  ```\n\n  对应的路由path为`/main/about/:id/:appid/:page`，这个跟PHP Yii的参数是一致的。\n\n### Controller规范\n\n- controller文件查找会根据上面的URL规范返回的controllerId，查找到设置的目录文件（会根据controllerId去查找文件，当然不是真实的文件查找，如果用webpack，webpack会帮你把文件关系一一对应起来）。例如建议这样设置controller文件（Controller.set用法请查看下面的Controller基类API）：\n\n  ```js\n  Controller.set({\n    readControllerFile(controllerId) {\n      //webpackMode: eager是使import变为不异步，跟require一样，\n      //但是返回的是promise对象，不能使用require，require会把没必要的文件载入\n      //最好不使用异步载入，可能导致一些问题\n      return import(/* webpackMode: \"eager\" */\n      `./controller/${controllerId}.js`)\n        .then(controller =\u003e {\n          return controller.default;\n        })\n        .catch(e =\u003e {\n          //必须catch并返回false\n          return false;\n        });\n    }\n  });\n  ```\n\n  或者还可以这样，通过switch来处理（没有使用webpack的时候）：\n\n  ```js\n  import main from './controller/main'\n  import test from './controller/test'\n  Controller.set({\n    readControllerFile(controllerId) {\n      //必须返回promies对象\n      return new Promise(function(resolve, reject) {\n        switch(controllerId) {\n          case 'main':\n            resolve(main);\n            break;\n          case 'test':\n            resolve(test);\n            break;\n        }\n      });\n    }\n  });\n  ```\n\n  上面使用webpack 3.x以上的import方式，import会把前面的整个`./controller`文件夹的所有文件做了一个映射，然后通过controllerId就可以import到指定文件。\n\n- controller 渲染view组件规范\n\n  **view函数=viewId+View，即xxxxView(){}。**\n\n  先看下代码：\n\n  ```js\n  import Controller from 'react-router-controller';\n  import LayoutComponent from '../view/layout/main';\n\n  export default class MainController extends Controller {\n    LayoutComponent = LayoutComponent;\n    aboutView(params) {\n      return this.render(\n        {\n          title: '关于',\n          breadcrumbs: [],\n        },\n        params\n      );\n    }\n  }\n  ```\n\n  像上面的controller中aboutView方法运行的pathname为`/main/about`。首先main先找到`./controller/main.js`文件，如果不存在返回404页面。存在就继续找view函数，然后运行view函数，否则返回404页面。\n\n## 使用入门\n\n使用create-react-app，创建一个demo app，下面的范例以这个app为基础来处理。例子可以看项目中的demo文件夹（这个demo不是用create-react-app创建的）。\n\n**demo/src/index.js**\n\n为了使用react-hot-loader，这需要一个container，controller的主要代码就在`demo/src/container.js`中。\n\n\u003e 这个入口文件如果使用了热替换，需要在`module.hot.accept`中把hot（需要使用随机数，保证每次热替换hot值都不一样）参数传到`\u003cContainer /\u003e`的prop.hot中，这样react-router-controller的热替换才会生效。\n\n```js\n//为了兼容IE的promise请加上polyfill\nimport 'react-router-controller/polyfill'\nimport React from 'react';\nimport { render } from 'react-dom';\n//使用react-hot-loader需要一个Container，可以参考react-hot-loader例子。\nimport Container from './container';\n\nfunction randomKey() {\n  return Math.random().toString(36).substring(7).split('').join('.');\n}\n\nfunction renderApp(hot) {\n  render(\u003cContainer hot={hot} /\u003e, document.getElementById('root'));\n}\nrenderApp();\nif (module.hot) {\n  module.hot.accept('./container', () =\u003e {\n    //controller的热替换需要特殊处理\n    //通过props.hot开启，要不会不生效\n    //而且要用随机数处理\n    var hot = randomKey();\n    return renderApp(hot);\n  });\n}\n```\n\n**demo/src/container.js**\n\n这里需要主要的就是view文件的读取，和controller文件的读取（建议使用webpack的import方式，当然也可以一个一个配置然后返回view组件或controller，但是这个麻烦，如果不使用webpack就要使用这种麻烦的方式了）。\n\nview和controller的目录在Controller.set中设置。\n\n```js\nimport React from 'react';\nimport Controller, { BrowserRouterController } from 'react-router-controller';\nimport nopage from './view/nopage';\n\nController.set({\n  readViewFile(viewId) {\n    //view可以异步载入\n    return import(`./view/${viewId}/index.js`).then(component =\u003e {\n      return component.default;\n    });\n  },\n  readControllerFile(controllerId) {\n    //webpackMode: eager是使import变为不异步，跟require一样，\n    //但是返回的时promise对象，不能使用require，require会把没必要的文件载入\n    //最好不适用异步载入，可能导致一些问题\n    return import(/* webpackMode: \"eager\" */\n    `./controller/${controllerId}.js`)\n      .then(controller =\u003e {\n        return controller.default;\n      })\n      .catch(e =\u003e {\n        //必须catch并返回false\n        return false;\n      });\n  },\n  \n  //设置404页面，会覆盖默认的404页面\n  NotMatchComponent: nopage,\n  //设置首页path（跳转路径，即react-router path='/'时，会跳转到indexPath）\n  //第一个字符必须是'/'，不能是main/index，要是绝对的路径\n  indexPath: '/main/index',\n});\n\nexport default function container(props) {\n  //basename的设置需要配合webpack使用，要不即使在开发环境没问题，但是成产环境\n  //访问根目录的basename文件夹（文件名为basename的值），会有问题的。\n  return (\n    \u003cBrowserRouterController\n      basename={process.env.PREFIX_URL}\n      hot={props.hot}\n    /\u003e\n  );\n}\n```\n\n然后就可以新建controller文件和view文件了。\n\n**src/controller/main.js**\n\n规范后续会说明，在xxxView按照下面的格式就会渲染出复合规则的view页面。\n\n```js\nimport Controller from 'react-router-controller';\nimport LayoutComponent from '../view/layout/main';\n\nexport default class MainController extends Controller {\n  LayoutComponent = LayoutComponent;\n  indexView(params) {\n    return this.render(\n      {\n        title: '主页',\n        breadcrumbs: [],\n      },\n      params\n    );\n  }\n  aboutView(params) {\n    if (!this.checkParams(params, ['id'])) {\n      return false;\n    }\n    return this.render(\n      {\n        title: '关于',\n        breadcrumbs: [],\n      },\n      params\n    );\n  }\n}\n```\n\n**view/index/index.js**\n\nview文件很简单，就像平常的react组件一样。\n\n```jsx\nimport React from 'react';\n\nclass IndexView extends React.Component {\n  render() {\n    console.debug('index页面');\n    return \u003cdiv\u003e主页页面\u003c/div\u003e;\n  }\n}\n\nexport default IndexView;\n```\n\n## API说明\n\n### Controller基类\n\n`import Controller from 'react-router-controller'`\n\n每新建一个controller都必须继承这个基类，**controller中xxView之间可以使用类变量通讯。**\n\n`Controller`这个类提供了一些方法和变量：\n\n- set(config)\n\n  **使用react-router-controller必须先用set配置**，可以参考demo。\n\n  **config.xx**\n\n  | config.xx          | 类型       | 说明                                       | 必填    |\n  | ------------------ | -------- | ---------------------------------------- | ----- |\n  | readControllerFile | function | 读取controller文件，必须返回promise对象。            | true  |\n  | readViewFile       | function | 读取view组件文件，必须返回promise对象。                | false |\n  | NotMatchComponent  | object   | react view 组件，404页面。                     | false |\n  | indexPath          | string   | 设置主页（因为controller规范原因，不存在'/'这种的pathname，格式都是/controllerId/viewId/paramsId/1），'/'会跳转到这个indexPath。 | true  |\n\n  **config.readControllerFile(controllerId)**\n\n  | 参数（param）    | 类型     | 说明                           | 必填   |\n  | ------------ | ------ | ---------------------------- | ---- |\n  | controllerId | string | 控制器文件名id，通过解析url得到，怎样使用看使用者。 | true |\n\n  **config.readViewFile(viewId,firstLoad)**\n\n  | 参数（param） | 类型      | 说明                                       | 必填    |\n  | --------- | ------- | ---------------------------------------- | ----- |\n  | viewId    | string  | view文件名id，通过解析url得到，怎样使用看使用者。            | true  |\n  | firstLoad | boolean | 判断当前函数，view文件是否是第一次载入（false未载入，true是载入），使用者或许可能用到。 | false |\n\n- render(config, params,ViewComponent) \n\n  每个`xxView`函数都要用到，名字虽然叫render，实际是还没渲染，只是返回传递了一个对象到react-router中使用。\n\n  | 参数（param）     | 类型     | 说明                                       | 必填    |\n  | ------------- | ------ | ---------------------------------------- | ----- |\n  | config        | object | 一些配置{title: '标题',breadcrumbs:['面包屑']}，还可以自定义。 | true  |\n  | params        | object | pathname解析后的参数如， {contollerId: 'main',viewId: 'about',id: \"100\",appid: 'aiermu' } | true  |\n  | ViewComponent | object | react view 组件，如果存在，覆盖默认的。                | false |\n\n- LayoutComponent\n\n  设置layout组件，不设置就没layout。\n\n- suffixTtile\n\n  设置后缀title，可选。\n\n- checkParams(params, paramsSetting)\n\n  根据传进来的参数，检查url的params是否符合controller指定的格式。\n\n  | 参数（param）     | 类型     | 说明                                       | 必填   |\n  | ------------- | ------ | ---------------------------------------- | ---- |\n  | params        | object | pathname解析后的参数如， {contollerId: 'main',viewId: 'about',id: \"100\",appid: 'aiermu' } | true |\n  | paramsSetting | array  | react-router参数，如['id','appid']（/main/about/:id/:appid） | true |\n\n### BrowserRouterController\n\n对react-router-dom中的`\u003cBrowserRouter /\u003e`进行controller封装，里面会根据url渲染对应的页面。\n\n用法如下：\n\n```jsx\nReactDOM.render(\u003cBrowserRouterController /\u003e, document.getElementById('root'));\n```\n\n| props       | 说明                                       | 默认值  |\n| ----------- | ---------------------------------------- | ---- |\n| hot         | react-hot-loader热替换开启，每次热替换需要传入不同的值，可用随机数。 | 无    |\n| other.props | 继承react-router中BrowserRouter的所用props。    | 无    |\n\n### HashRouterController\n\n对react-router-dom中的`\u003cHashRouter /\u003e`进行controller封装，里面会根据url渲染对应的页面。\n\n用法如下：\n\n```jsx\nReactDOM.render(\u003cHashRouterController /\u003e, document.getElementById('root'));\n```\n\n| props       | 说明                                       | 默认值  |\n| ----------- | ---------------------------------------- | ---- |\n| hot         | react-hot-loader热替换开启，每次热替换需要传入不同的值，可用随机数。 | 无    |\n| other.props | 继承react-router中HashRouter的所用props。       | 无    |\n\n### MemoryRouterController\n\n对react-router-dom中的`\u003cMemoryRouter /\u003e`进行controller封装，里面会根据内存渲染对应的页面。\n\n用法如下：\n\n```jsx\nReactDOM.render(\u003cMemoryRouterController /\u003e, document.getElementById('root'));\n```\n\n| props       | 说明                                       | 默认值  |\n| ----------- | ---------------------------------------- | ---- |\n| hot         | react-hot-loader热替换开启，每次热替换需要传入不同的值，可用随机数。 | 无    |\n| other.props | 继承react-router中MemoryRouter的所用props。     | 无    |\n\n### Layout组件\n\n使用者传进来的layout组件，react-router-controller会为这个组件添加以下props:\n\n- params\n\n  例如`http://localhost/main/about/id/10`的param如下：\n\n  ```js\n  {controllerId: 'main',viewId: 'about',id: 10}\n  ```\n\n- breadcrumbs\n\n  格式随意定，从Controller的render方法第一个参数传进来。\n\n- viewConfig\n\n  所有的view配置，包括title、breadcrumbs和一些自定义的配置，看情况使用，大多数情况用不到的。\n\n### View组件\n\n使用者传进来的layout组件，react-router-controller会为这个组件添加以下props:\n\n- params\n\n  同Layout组件。\n\n- title\n\n  页面title设置。\n\n- viewConfig\n\n  同Layout组件。\n\n\n## 插件\n\n**插件其实就是个函数**，插件都需要返回一个json对象，这个json对象可以在view组件和layout组件props，还有controller的`xxView`方法中第二个参数中访问到。\n\n插件都需要在`Controlle.set`配置：\n\n```js\nController.set({\n  plugins: [plugin1,plugin2]\n})\n```\n\n### i18n插件\n\n#### **参数说明**\n\n| 参数                  | 类型       | 说明                                       | 必填   |\n| ------------------- | -------- | ---------------------------------------- | ---- |\n| switchLanguageList  | function | 切换语言，参数是语言名称。返回的可以是promise（promise中返回的是语言数组列表），也可以直接语言数组列表。最好使用webpack的异步import。 | true |\n| defaultLanguageList | array    | 默认的语言列表                                  | true |\n\n#### **返回值**\n\n| 返回值            | 类型       | 说明                  |\n| -------------- | -------- | ------------------- |\n| t              | function | 用作翻译转换，默认参数是需要翻译的文案 |\n| switchLanguage | function | 默认的语言列表             |\n| displayName    | string   | 插件命名，值为i18n。        |\n\n#### 使用\n\n配置文件\n\n```js\nController.set({\n  plugins: [\n    i18n(language =\u003e {\n      return import(`./i18n/${language}.js`).catch(e =\u003e {\n        console.log(e);\n        return false;\n      });\n    }, require('./i18n/zh_CN').default),\n  ]\n})\n```\n\n经过配置，react-router-controller运行后，layout组件和view组件的props都可以访问`props.i18n`，还有controller的`xxView`方法中第二个参数也可以访问到这个对象。\n\n使用i18n传进来的对象：\n\n```jsx\nimport React from 'react';\n\nclass AboutView extends React.Component {\n  render() {\n    console.debug('about页面');\n    const { i18n: { t } } = this.props;\n    return (\n      \u003cdiv\u003e\n        {t('关于页面')}\n      \u003c/div\u003e\n    );\n  }\n}\nexport default AboutView;\n```\n\ncontroller文件\n\n```js\nimport Controller from 'react-router-controller';\nexport default class MainController extends Controller {\n  aboutView(params, { i18n: { t } }) {\n    return this.render(\n      {\n        title: t('关于'),\n        breadcrumbs: [\n          {\n            link: `/main/about/id/${params.id}`,\n            label: t('关于'),\n          },\n        ],\n      },\n      params\n    );\n  }\n}\n```\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdog-days%2Freact-router-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdog-days%2Freact-router-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdog-days%2Freact-router-controller/lists"}