Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-router-controller

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-router-controller

react-router-controller,react路由控制器

  • 0.0.4
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
16
increased by166.67%
Maintainers
1
Weekly downloads
 
Created
Source

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规范(非常简单的规范)。

使用规范

就像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参数设置名,后面的是参数值(成对出现,理论是可以无限个)。例如urlhttp://localhost:8000/main/about/id/100/appid/test/page/2,会解析成params(controller xxxView函数参数、layout组件和view组件的props.params):

    {
      controllerId: "main",
      viewId: "about",
      id: "100",
      appid: "test",
      page: "2"
    }
    

    对应的路由path为/main/about/:id/:appid/:page,这个跟PHP Yii的参数是一致的。

Controller规范

  • controller文件查找会根据上面的URL规范返回的controllerId,查找到设置的目录文件(会根据controllerId去查找文件,当然不是真实的文件查找,如果用webpack,webpack会帮你把文件关系一一对应起来)。例如建议这样设置controller文件(Controller.set用法请查看下面的Controller基类API):

    Controller.set({
      readControllerFile(controllerId) {
        //webpackMode: eager是使import变为不异步,跟require一样,
        //但是返回的是promise对象,不能使用require,require会把没必要的文件载入
        //最好不使用异步载入,可能导致一些问题
        return import(/* webpackMode: "eager" */
        `./controller/${controllerId}.js`)
          .then(controller => {
            return controller.default;
          })
          .catch(e => {
            //必须catch并返回false
            return false;
          });
      }
    });
    

    上面使用webpack 3.x以上的import方式,import会把前面的整个./controller文件夹的所有文件做了一个映射,然后通过controllerId就可以import到指定文件。

  • controller 渲染view组件规范

    view函数=viewId+View,即xxxxView(){}。

    先看下代码:

    import Controller from 'react-router-controller';
    import LayoutComponent from '../view/layout/main';
    
    export default class MainController extends Controller {
      LayoutComponent = LayoutComponent;
      aboutView(params) {
        return this.render(
          {
            title: '关于',
            breadcrumbs: [],
          },
          params
        );
      }
    }
    

    像上面的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的热替换才会生效。

import React from 'react';
import { render } from 'react-dom';
import Container from './container';

function randomKey() {
  return Math.random().toString(36).substring(7).split('').join('.');
}

function renderApp(hot) {
  render(<Container hot={hot} />, document.getElementById('root'));
}
renderApp();
if (module.hot) {
  module.hot.accept('./container', () => {
    //controller的热替换需要特殊处理
    //通过props.hot开启,要不会不生效
    //而且要用随机数处理
    var hot = randomKey();
    return renderApp(hot);
  });
}

demo/src/container.js

这里需要主要的就是view文件的读取,和controller文件的读取(建议使用webpack的import方式,当然也可以一个一个配置然后返回view组件或controller,但是这个麻烦,如果不使用webpack就要使用这种麻烦的方式了)。

view和controller的目录在Controller.set中设置。

import React from 'react';
import Controller, { BrowserRouterController } from 'react-router-controller';
import nopage from './view/nopage';

Controller.set({
  readViewFile(viewId) {
    //view可以异步载入
    return import(`./view/${viewId}/index.js`).then(component => {
      return component.default;
    });
  },
  readControllerFile(controllerId) {
    //webpackMode: eager是使import变为不异步,跟require一样,
    //但是返回的时promise对象,不能使用require,require会把没必要的文件载入
    //最好不适用异步载入,可能导致一些问题
    return import(/* webpackMode: "eager" */
    `./controller/${controllerId}.js`)
      .then(controller => {
        return controller.default;
      })
      .catch(e => {
        //必须catch并返回false
        return false;
      });
  },
  
  //设置404页面,会覆盖默认的404页面
  NotMatchComponent: nopage,
  //设置首页path(跳转路径,即react-router path='/'时,会跳转到indexPath)
  //第一个字符必须是'/',不能是main/index,要是绝对的路径
  indexPath: '/main/index',
});

export default function container(props) {
  //basename的设置需要配合webpack使用,要不即使在开发环境没问题,但是成产环境
  //访问根目录的basename文件夹(文件名为basename的值),会有问题的。
  return (
    <BrowserRouterController
      basename={process.env.PREFIX_URL}
      hot={props.hot}
    />
  );
}

然后就可以新建controller文件和view文件了。

src/controller/main.js

规范后续会说明,在xxxView按照下面的格式就会渲染出复合规则的view页面。

import Controller from 'react-router-controller';
import LayoutComponent from '../view/layout/main';

export default class MainController extends Controller {
  LayoutComponent = LayoutComponent;
  indexView(params) {
    return this.render(
      {
        title: '主页',
        breadcrumbs: [],
      },
      params
    );
  }
  aboutView(params) {
    if (!this.checkParams(params, ['id'])) {
      return false;
    }
    return this.render(
      {
        title: '关于',
        breadcrumbs: [],
      },
      params
    );
  }
}

view/index/index.js

view文件很简单,就像平常的react组件一样。

import React from 'react';

class IndexView extends React.Component {
  render() {
    console.debug('index页面');
    return <div>主页页面</div>;
  }
}

export default IndexView;

API说明

Controller基类

import Controller from 'react-router-controller'

每新建一个controller都必须继承这个基类,这个类提供了一些方法:

  • set(config)

    使用react-router-controller必须先用set配置,可以参考demo。

    config.xx

    config.xx类型说明必填
    readControllerFilefunction读取controller文件,必须返回promise对象。true
    readViewFilefunction读取view组件文件,必须返回promise对象。false
    NotMatchComponentobjectreact view 组件,404页面。false
    indexPathstring设置主页(因为controller规范原因,不存在'/'这种的pathname,格式都是/controllerId/viewId/paramsId/1),'/'会跳转到这个indexPath。true

    config.readControllerFile(controllerId)

    参数(param)类型说明必填
    controllerIdstring控制器文件名id,通过解析url得到,怎样使用看使用者。true

    config.readViewFile(viewId,firstLoad)

    参数(param)类型说明必填
    viewIdstringview文件名id,通过解析url得到,怎样使用看使用者。true
    firstLoadboolean判断当前函数,view文件是否是第一次载入(false未载入,true是载入),使用者或许可能用到。false
  • render(viewId, config, params)

    名字叫render,实际是还没渲染,只是返回传递了一个对象到react-router中使用。

    参数(param)类型说明必填
    configobject一些配置{title: '标题',breadcrumbs:['面包屑']},还可以自定义。true
    paramsobjectpathname解析后的参数如, {contollerId: 'main',viewId: 'about',id: "100",appid: 'aiermu' }true
    ViewComponentobjectreact view 组件,如果存在,覆盖默认的。false
  • LayoutComponent

    设置layout组件,不设置就没layout。

  • checkParams(params, paramsSetting)

    根据传进来的参数,检查url的params是否符合controller指定的格式。

    参数(param)类型说明必填
    paramsobjectpathname解析后的参数如, {contollerId: 'main',viewId: 'about',id: "100",appid: 'aiermu' }true
    paramsSettingarrayreact-router参数,如['id','appid'](/main/about/:id/:appid)true

BrowserRouterController

对react-router-dom中的<BrowserRouter />进行controller封装,里面会根据url渲染对应的页面。

用法如下:

ReactDOM.render(<BrowserRouterController />, document.getElementById('root'));
props说明默认值
hotreact-hot-loader热替换开启,每次热替换需要传入不同的值,可用随机数。
other.props继承react-router中BrowserRouter的所用props。

HashRouterController

对react-router-dom中的<HashRouter />进行controller封装,里面会根据url渲染对应的页面。

用法如下:

ReactDOM.render(<HashRouterController />, document.getElementById('root'));
props说明默认值
hotreact-hot-loader热替换开启,每次热替换需要传入不同的值,可用随机数。
other.props继承react-router中HashRouter的所用props。

MemoryRouterController

对react-router-dom中的<MemoryRouter />进行controller封装,里面会根据内存渲染对应的页面。

用法如下:

ReactDOM.render(<MemoryRouterController />, document.getElementById('root'));
props说明默认值
hotreact-hot-loader热替换开启,每次热替换需要传入不同的值,可用随机数。
other.props继承react-router中MemoryRouter的所用props。

Keywords

FAQs

Package last updated on 14 Aug 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc