Giter Site home page Giter Site logo

san-router's Introduction

san-router

NPM version License

San 框架的官方 router,支持动态路由,嵌套路由,路由懒加载以及导航守卫等功能。

注意:使用 san-router,要求 San 的版本号 >= 3.0.2

文档 | 示例项目

下载

# use npm
npm i san-router
# or use yarn
yarn add san-router

使用

如需了解更多功能,请访问 快速开始

import {router, Link} from 'san-router';

router.add({
    rule: '/book',
    Component: BookDetail
});
router.add([
    {
        rule: '/about',
        Component: About
    },
    {
        rule: '/home',
        Component: Home
    }
]);
router.start();

CHANGELOG

CHANGELOG

License

san-router is MIT licensed.

san-router's People

Contributors

buptlhuanyu avatar dafrok avatar dependabot[bot] avatar erik168 avatar errorrik avatar gnipbao avatar jiangjiu avatar jinzhan avatar leeight avatar leuisken avatar vanishcode avatar vincentmrlau avatar wuhy avatar zxhfighter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

san-router's Issues

在router的listen方法中要跳转到另外一个路由中,无法中断前一个路由对应组件的行为

现象:我在全局增加了router.listen方法,希望通过该方法来实现全局的auth控制,但是当我需要跳转到其它路由时(使用的是location.href),前一个路由对应的组件的行为仍然被执行了。例如现在有/a、/b两个路由,分别对应组件A,B。当我访问/a时,如果在router.listen监听中,进过判断要跳转到/b。此时/a的组件行为被执行了,如inited(),attached()。
建议: 在全局路由中发生跳转后,只执行将要跳转到的路由对应的组件行为。

基本模块

san-router的功能很简单,通过一个URL的输入,经过一系列的计算,定位到一个函数去执行,效果类似er中的locator + router部分,后面复杂的controller等功能不在san-router中提供,可根据与具体的UI库整合来实现

Locator

其实想改个名,这名字有点蛋疼……

Locator负责监听URL的变化并触发相应的事件,核心的方法:

  • {void} forward({string|URL} url)
  • {void} start()
  • {void} stop()

forward是否允许silent待定,�看具体应用场景

可以对应实现HistoryLocatorHashLocator

Parser

负责将URL按照格式解析出参数等工作,核心的方法:

  • {RouteContext} parse({string}URL} url)

默认实现支持类RESTful格式的URL的解析

Registry

负责注册URL至函数的映射,并通过解析后的URL得到对应的函数,核心方法:

  • {RouteConfig} resolve({RouteContext} context)
  • {void} register({RouteConfig} config)

Middleware

中间件是一个函数,符合以下范式:

{RouteContext} async middleware({RouteContext} context)

Dispatcher

Dispatcher是把上面的东西组合起来用,提供唯一的{void} start()方法

不能正确匹配使用合法 unicode 作为 param 的路由

问题:不能正确匹配使用合法 unicode 作为 param 的路由

现象

使用 san-router 时,如果使用中文路由作为 param,组件无法成功挂载。

复现步骤

import {router} from 'san-router'
import App from '@/App.san'

router.add({
  rule: '/:param',
  Component: App,
  target: 'body'
})

router.start()
  • 开启本地静态服务器
  • 访问 http://localhost/excited,能够正确挂载 App 组件。
  • 访问 http://localhost/一颗赛艇,发现 App 组件被续了。
  • 将 '一颗赛艇' 转换为 uriComponent,仍然被续。

原因

查看 san-router.source.js: line 981,正则匹配 param 仅匹配 [a-z0-9_-],而忽略了其它合法 unicode 和 uriComponent 的转义符 '%'。

var regText = rule.replace(/\/:([a-z0-9_-]+)(?=\/|$)/g, function (match, key) {
  keys.push(key);
  return '/([a-z0-9_-]+)';
});

2.0.2版本的类型文件有错误 type Mode = 'hash' | 'history'

类型定义的是:
type Mode = 'hash' | 'history';
但是代码里判断的时候是使用的 'html5',导致 setMode('history') 方法获取到的 locator 仍然是 HashLocator
另外 Router 也缺少带参数的构造,导致在 ts 下自定义路由实例时不能传参呀

使用npm安装的san-router有问题

使用 npm i san-router 来安装 san-router 有问题。提示 6547 列的 set 方法不存在。

但是使用此仓库重新生成 npm run build 就可以了。

不知道是什么情况。

如何实现404的功能

能否添加一条路由,这个路由可以匹配所有其他规则无法匹配的路径,从而实现404页面之类的功能

[feature request] 嵌套路由和异步组件

场景
6407460ba0537a010681afc5364ade85
https://juejin.im/welcome/frontend
可以看到这个网址有两级路由,每一级分别对应一层多Tab。

目前cms这边存在类似的场景,如果没有二级路由和异步组件的话,拆分组件和数据加载是个很头疼的事儿。

问题
异步组件配合webpack比较好解决
嵌套路由的话,
目前san只能通过attach方法渲染到指定dom,暂时想不到嵌套子路由如何继承父子组件关系和属性。

一个关于测试用例的问题

首先上有问题的代码段 /test/index.js 第 16 行至 51 行:

router.setMode('hash');
router.start();

let routeTimes = 0;
let App = san.defineComponent({
    initData() {
        return {
            routeTimes: 0
        };
    },

    components: {
        'router-link': Link
    },

    route() {
        this.data.set('routeTimes', this.data.get('routeTimes') + 1);
        routeTimes = this.data.get('routeTimes');
    },

    template: '<div><router-link to="./errorrik">Click here to hash route, quickly</router-link>  <b title="{{route.query.name}}">{{route.query.name}}</b></div>'
});

router.add({
    rule: '/synthesis/hash/:name',
    Component: App
});

location.hash = '/synthesis/hash/erik';

setTimeout(() => {
    expect(routeTimes).toBe(1);
    expect(document.getElementById('main').getElementsByTagName('b')[0].title).toBe('erik');
    detectDone();
}, 500);

根据断言的描述 hash mode, link to route,可以得知这是测试 hash mode 下 router-link 组件是否正常工作的测试用例。

这段代码的逻辑是先创建一个组件,然后挂到路由上,然后同步更改 hash 值,再异步检测组件中的 router-link 是否被点击。从同步的 hash 变更到开始检测的延迟为 500 毫秒。
显然,如果在 500 在毫秒内进行点击的话,location.hash 会提前发生变化,于是定时器中的句柄执行后将不会得到期望的值。

然而 router-link 提示是 Click here to hash route, quickly,于是我根据提示,用高于 500ms / 次的频度迅速点击该链接,导致了单元测试失败;而等到 500ms 之后再去点击,却是(意料之中的)成功。

因此我推测这个测试用例在某种程度上是有问题的。要么是链接的提示产生了误导,要么是断言对测试项的描述有歧义,亦或测试用例本身的实现不够严谨。

P.S. 75 行的 html5 mode 的测试用例有同样的问题。

测试案例 'by handler, should call handler, match non ascii string as rule :xxx' 在 ie 下运行出错

1. 版本: 1.2.4

2. 测试用例:

expect(e.params.name).toBe('%E4%BD%A0%E5%A5%BD');

在 ie8 或 ie11 下运行出错。

3. 原因分析:

ie下的 hash 没有对中文URI 进行编码,其 location.hash 和 location.href 都保留中文编码:

  • hash: #/route-test/non/asc/你好
  • href: http://127.0.0.1:5500/test/?spec=Router%20by%20handler%2C%20should%20call%20handler%2C%20match%20non%20ascii%20string%20as%20rule%20%3Axxx#/route-test/non/asc/你好

4. 建议:

在代码

var value = match[j];

中增加 decodeURIComponent

[feature request] keep-alive节点

目前业务经常性的从列表中某一项跳到一个编辑页面,返回后又要重新填充各个筛选项,走生命周期中的方法,希望能提供个alive节点,对页面状态做缓存,这样会极大的方便开发。

redirect

locator.reload无效,当前业务需求需要刷新组件, {force:true}无效

轮换式路由集群

这一功能用在预加载方面有奇效

  1. 定义抽象的路由生命周期,重点是将一个路由的目标的生命周期分隔为渲染前渲染这两个阶段
  2. 一个集群中包含多个路由实例,其中永远只有一个处于渲染状态,称为前端实例,其它称为后端实例
  3. 后端实例可用于命令式地接受一个新的路由,其功能是根据路由找到对应的模块,执行渲染前阶段的逻辑,但不渲染,这个逻辑包含了初始化、数据加载等一系列工作,然后这个状态被保存下来
  4. 当实际URL变化时,路由集群会试图查看后端路由里是否有一个与当前的URL配对,如果配对的知,把这个路由提上来作为前端路由,立即执行渲染这个阶段的工作,因为之前作为后端路由时已经完成了渲染前的所有工作,因此可以非常快速地出界面
  5. 此时原来的前端路由状态被清空,放进后端路由池中等待指令

可以通过配置后端路由的数量来控制可并行的预加载的量,使用不同的淘汰策略来确保预加载的命中率

微前端场景下第二次不渲染

子应用使用san-router,第二次加载该子应用的时候无法正常渲染。在子应用卸载的时候调用

router.stop()

不能完全解决问题,需要

router.stop();
router.routes = [];
router.routeAlives = [];
router.listeners = [];
router.locator.current = '/';

之后才可以正常使用。可否提供一个api来实现类似需求。

如果是 Async Component 的话,应该支持更多其它的配置

例如:https://vuejs.org/v2/guide/components.html#Async-Components

const MyComponent = () => ({
  // The component to load. Should be a Promise
  component: import('./MyComponent'),
  // A component to use while the async component is loading
  loading: LoadingComp,
  // A component to use if the load fails
  error: ErrorComp,
  // Delay before showing the loading component. Default: 200ms.
  delay: 200,
  // The error component will be displayed if a timeout is
  // provided and exceeded. Default: Infinity.
  timeout: 3000
});

嵌套路由

既然不支持嵌套路由,那有啥办法做后台管理系统那种:左侧菜单,右侧内容?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.