React Router Controller
react-router-controller启发于PHP Yii框架,实现了根据url动态渲染页面(这得益于react-router@4.x.x实现的动态路由)。
建议配合webpack使用
这个路由从始至终都只运行了一个路由配置,因为这个路由是动态的,不存在同时存在其他路由配置。
为什么要使用这个
-
无路由配置
-
后端控制器模式
react-router-controller是MVC中的VC,React是View,Controller是C,再配合redux或者mobx就是MVC模式了。思路简单明了,专心于业务逻辑即可。
缺点
用这个当然会有点限制,不能自定义路由(定义路由需要遵循controller规范,页面内部的多级动态路由不影响,可以随意定,但是不建议使用子路由)。
兼容性
一般主流浏览器都兼容。
-
chrome浏览器最新版
-
火狐浏览器最新版
-
Edge浏览器最新版
-
IE浏览器支持IE9版本以上(包括IE9)
因为IE不支持promise,所以需要引入polyfill.js。
//如果已经有相关的promise polyfill,可以不用这个。
使用规范
就像PHP Yii一样(90%相似),react-router-controller也有自己的规范。
URL规范
跟Yii基本一致,处理没有module这分类。
-
controllerId和viewId
url必须要包括controllerId和viewId(controller名和view名,为了解析成动态路由),例如
http://localhost:8000/main/about
,这个路由会解析成参数传入controller的view函数中({conrollerId: main,vieId: about}
)。 -
路由参数
除开controllerId和viewId外,后面url接的参数也有一定的规则,前面第一个是react-router参数设置名,后面的是参数值(成对出现,理论是可以无限个)。例如url
http://localhost:8000/main/about/id/100/appid/test/page/2
,会解析成params(controller xxxView函数参数、layout组件和view组件的props.params):对应的路由path为
/main/about/:id/:appid/:page
,这个跟PHP Yii的参数是一致的。
Controller规范
-
controller文件查找会根据上面的URL规范返回的controllerId,查找到设置的目录文件(会根据controllerId去查找文件,当然不是真实的文件查找,如果用webpack,webpack会帮你把文件关系一一对应起来)。例如建议这样设置controller文件(Controller.set用法请查看下面的Controller基类API):
Controller;或者还可以这样,通过switch来处理(没有使用webpack的时候):
Controller;上面使用webpack 3.x以上的import方式,import会把前面的整个
./controller
文件夹的所有文件做了一个映射,然后通过controllerId就可以import到指定文件。 -
controller 渲染view组件规范
view函数=viewId+View,即xxxxView(){}。
先看下代码:
;;LayoutComponent = LayoutComponent;{return this;}像上面的controller中aboutView方法运行的pathname为
/main/about
。首先main先找到./controller/main.js
文件,如果不存在返回404页面。存在就继续找view函数,然后运行view函数,否则返回404页面。
使用入门
使用create-react-app,创建一个demo app,下面的范例以这个app为基础来处理。例子可以看项目中的demo文件夹(这个demo不是用create-react-app创建的)。
demo/src/index.js
为了使用react-hot-loader,这需要一个container,controller的主要代码就在demo/src/container.js
中。
这个入口文件如果使用了热替换,需要在
module.hot.accept
中把hot(需要使用随机数,保证每次热替换hot值都不一样)参数传到<Container />
的prop.hot中,这样react-router-controller的热替换才会生效。
//为了兼容IE的promise请加上polyfill;;//使用react-hot-loader需要一个Container,可以参考react-hot-loader例子。; { return Math;} { ;};if modulehot modulehotaccept'./container' { //controller的热替换需要特殊处理 //通过props.hot开启,要不会不生效 //而且要用随机数处理 var hot = ; return ; };
demo/src/container.js
这里需要主要的就是view文件的读取,和controller文件的读取(建议使用webpack的import方式,当然也可以一个一个配置然后返回view组件或controller,但是这个麻烦,如果不使用webpack就要使用这种麻烦的方式了)。
view和controller的目录在Controller.set中设置。
;;; Controller; { //basename的设置需要配合webpack使用,要不即使在开发环境没问题,但是成产环境 //访问根目录的basename文件夹(文件名为basename的值),会有问题的。 return <BrowserRouterController basename=processenvPREFIX_URL hot=propshot /> ;}
然后就可以新建controller文件和view文件了。
src/controller/main.js
规范后续会说明,在xxxView按照下面的格式就会渲染出复合规则的view页面。
;; LayoutComponent = LayoutComponent; { return this; } { if !this return false; return this; }
view/index/index.js
view文件很简单,就像平常的react组件一样。
import React from 'react'; Component { console; return <div>主页页面</div>; } ;
API说明
Controller基类
import Controller from 'react-router-controller'
每新建一个controller都必须继承这个基类,controller中xxView之间可以使用类变量通讯。
Controller
这个类提供了一些方法和变量:
-
set(config)
使用react-router-controller必须先用set配置,可以参考demo。
config.xx
config.xx 类型 说明 必填 readControllerFile function 读取controller文件,必须返回promise对象。 true readViewFile function 读取view组件文件,必须返回promise对象。 false NotMatchComponent object react view 组件,404页面。 false indexPath string 设置主页(因为controller规范原因,不存在'/'这种的pathname,格式都是/controllerId/viewId/paramsId/1),'/'会跳转到这个indexPath。 true config.readControllerFile(controllerId)
参数(param) 类型 说明 必填 controllerId string 控制器文件名id,通过解析url得到,怎样使用看使用者。 true config.readViewFile(viewId,firstLoad)
参数(param) 类型 说明 必填 viewId string view文件名id,通过解析url得到,怎样使用看使用者。 true firstLoad boolean 判断当前函数,view文件是否是第一次载入(false未载入,true是载入),使用者或许可能用到。 false -
render(config, params,ViewComponent)
每个
xxView
函数都要用到,名字虽然叫render,实际是还没渲染,只是返回传递了一个对象到react-router中使用。参数(param) 类型 说明 必填 config object 一些配置{title: '标题',breadcrumbs:['面包屑']},还可以自定义。 true params object pathname解析后的参数如, {contollerId: 'main',viewId: 'about',id: "100",appid: 'aiermu' } true ViewComponent object react view 组件,如果存在,覆盖默认的。 false -
LayoutComponent
设置layout组件,不设置就没layout。
-
suffixTtile
设置后缀title,可选。
-
checkParams(params, paramsSetting)
根据传进来的参数,检查url的params是否符合controller指定的格式。
参数(param) 类型 说明 必填 params object pathname解析后的参数如, {contollerId: 'main',viewId: 'about',id: "100",appid: 'aiermu' } true paramsSetting array react-router参数,如['id','appid'](/main/about/:id/:appid) true
BrowserRouterController
对react-router-dom中的<BrowserRouter />
进行controller封装,里面会根据url渲染对应的页面。
用法如下:
ReactDOM;
props | 说明 | 默认值 |
---|---|---|
hot | react-hot-loader热替换开启,每次热替换需要传入不同的值,可用随机数。 | 无 |
other.props | 继承react-router中BrowserRouter的所用props。 | 无 |
HashRouterController
对react-router-dom中的<HashRouter />
进行controller封装,里面会根据url渲染对应的页面。
用法如下:
ReactDOM;
props | 说明 | 默认值 |
---|---|---|
hot | react-hot-loader热替换开启,每次热替换需要传入不同的值,可用随机数。 | 无 |
other.props | 继承react-router中HashRouter的所用props。 | 无 |
MemoryRouterController
对react-router-dom中的<MemoryRouter />
进行controller封装,里面会根据内存渲染对应的页面。
用法如下:
ReactDOM;
props | 说明 | 默认值 |
---|---|---|
hot | react-hot-loader热替换开启,每次热替换需要传入不同的值,可用随机数。 | 无 |
other.props | 继承react-router中MemoryRouter的所用props。 | 无 |
Layout组件
使用者传进来的layout组件,react-router-controller会为这个组件添加以下props:
-
params
例如
http://localhost/main/about/id/10
的param如下:controllerId: 'main'viewId: 'about'id: 10 -
breadcrumbs
格式随意定,从Controller的render方法第一个参数传进来。
-
viewConfig
所有的view配置,包括title、breadcrumbs和一些自定义的配置,看情况使用,大多数情况用不到的。
View组件
使用者传进来的layout组件,react-router-controller会为这个组件添加以下props:
-
params
同Layout组件。
-
title
页面title设置。
-
viewConfig
同Layout组件。
插件
插件其实就是个函数,插件都需要返回一个json对象,这个json对象可以在view组件和layout组件props,还有controller的xxView
方法中第二个参数中访问到。
插件都需要在Controlle.set
配置:
Controller
i18n插件
参数说明
参数 | 类型 | 说明 | 必填 |
---|---|---|---|
switchLanguageList | function | 切换语言,参数是语言名称。返回的可以是promise(promise中返回的是语言数组列表),也可以直接语言数组列表。最好使用webpack的异步import。 | true |
defaultLanguageList | array | 默认的语言列表 | true |
返回值
返回值 | 类型 | 说明 |
---|---|---|
t | function | 用作翻译转换,默认参数是需要翻译的文案 |
switchLanguage | function | 默认的语言列表 |
displayName | string | 插件命名,值为i18n。 |
使用
配置文件
Controller
经过配置,react-router-controller运行后,layout组件和view组件的props都可以访问props.i18n
,还有controller的xxView
方法中第二个参数也可以访问到这个对象。
使用i18n传进来的对象:
import React from 'react'; Component { console; const i18n: t = thisprops; return <div> </div> ; };
controller文件
; { return this; }