精选文章 Dojo 路由

Dojo 路由

作者:weixin_34186931 时间: 2019-02-05 05:06:32
weixin_34186931 2019-02-05 05:06:32

路由

dojo/framework/src/routing/README.md

commit b682b06ace25eea86d190e56dd81042565b35ed1

Dojo 应用程序的路由

Features

部件(Widget)是 Dojo 应用程序的基本概念,因此 Dojo 路由提供了一组与应用程序中的部件直接集成的组件。这些组件能将部件注册到路由上,且不需要掌握路由相关的任何知识。Dojo 应用程序中的路由包括以下内容:

  • Outlet 部件封装器指定 route 的 outlet key 和表现视图之间的映射关系
  • Route 配置,用于在路径和 outlet key 之间建立映射关系
  • Router 基于当前路径解析 Route
  • History 提供器负责向 Router 通知路径的更改
  • RegistryRouter 注入到部件系统中

Route 配置

RouteConfig 用于注册应用程序的路由,它定义了路由的 path、关联的 outlet 以及嵌套的子 RouteConfig。一个完整的路由就是由递归嵌套的 Route 构成的。

路由配置示例:

import { RouteConfig } from '@dojo/framework/routing/interfaces';

const config: RouteConfig[] = [
    {
        path: 'foo',
        outlet: 'root',
        children: [
            {
                path: 'bar',
                outlet: 'bar'
            },
            {
                path: 'baz',
                outlet: 'baz',
                children: [
                    {
                        path: 'qux',
                        outlet: 'qux'
                    }
                ]
            }
        ]
    }
];

此配置将注册以下路由和 outlet:

Route Outlet
/foo root
/foo/bar bar
/foo/baz baz
/foo/baz/qux qux

路径参数

RouteConfig 的 path 属性中,在 path 的值中使用大括号可定义路径参数。 Parameters will match any segment and the value of that segment is made available to matching outlets via the mapParams Outlet options. The parameters provided to child outlets will include any parameters from matching parent routes.

const config = [
    {
        path: 'foo/{foo}',
        outlet: 'foo'
    }
];

具有路径参数的路由,可为每个路由指定默认的参数。当用没有指定参数的 outlet 生成一个链接,或者当前路由中不存在参数时,可使用这些默认参数值。

const config = [
    {
        path: 'foo/{foo}',
        outlet: 'foo',
        defaultParams: {
            foo: 'bar'
        }
    }
];

可使用可选的配属属性 defaultRoute 来设置默认路由,如果当前路由没有匹配到已注册的路由,就使用此路由。

const config = [
    {
        path: 'foo/{foo}',
        outlet: 'foo',
        defaultRoute: true
    }
];

Router

Router 用于注册 route 配置,将 route 配置信息传入 Router 的构造函数即可:

const router = new Router(config);

会自动为 router 注册一个 HashHistory 历史管理器(history manager)。可在第二个参数中传入其他历史管理器。

import { MemoryHistory } from '@dojo/framework/routing/MemoryHistory';

const router = new Router(config, { HistoryManager: MemoryHistory });

使用应用程序路由配置创建路由后,需要让应用程序中的所有组件可使用这些路由。这是通过使用 @dojo/framework/widget-core/Registry 中的 Registry,定义一个将 invalidator 连接到 router 的 nav 事件的注入器,并返回 router 实例实现的。这里使用 key 来定义注入器,路由器的默认 key 值为 router

import { Registry } from '@dojo/framework/widget-core/Registry';
import { Injector } from '@dojo/framework/widget-core/Injector';

const registry = new Registry();

// 假设我们有一个可用的 router 实例
registry.defineInjector('router', () => {
    router.on('nav', () => invalidator());
    return () => router;
};

注意: 路由提供了 注册 router 的快捷方法

最后,为了让应用程序中的所有部件都能使用 registry,需要将其传给 vdom renderer.mount() 方法。

const r = renderer(() => v(App, {}));
r.mount({ registry });

History Managers

路由自带三个历史管理器,用于监视和更改导航状态:HashHistoryStateHistoryMemoryHistory。默认使用 HashHistory,但是可在创建 Router 时传入不同的 HistoryManager

const router = new Router(config, { HistoryManager: MemoryHistory });
Hash History

基于哈希的管理器使用片段标识符(fragment identifier)来存储导航状态,是 @dojo/framework/routing 中的默认管理器。

import { Router } from '@dojo/framework/routing/Router';
import { HashHistory } from '@dojo/framework/routing/history/HashHistory';

const router = new Router(config, { HistoryManager: HashHistory });

历史管理器有 currentset(path: string)prefix(path: string) 三个API。HashHistory 类假定全局对象是浏览器的 window 对象,但可以显式提供对象。管理器使用 window.location.hashhashchange 事件的事件监听器。current 访问器返回当前路径,不带 # 前缀。

State History

基于状态的历史管理器使用浏览器的 history API:pushState()replaceState(),来添加和修改历史纪录。状态历史管理器需要服务器端支持才能有效工作。

Memory History

MemoryHistory 不依赖任何浏览器 API,而是保持其自身的内部路径状态。不要在生产应用程序中使用它,但在测试路由时却很有用。

import { Router } from '@dojo/framework/routing/Router';
import { MemoryHistory } from '@dojo/framework/routing/history/MemoryHistory';

const router = new Router(config, { HistoryManager: MemoryHistory });

Outlet Event

当每次进入或离开 outlet 时,都会触发 router 实例的 outlet 事件。outlet 上下文、enterexit 操作都会传给事件处理函数。

router.on('outlet', ({ outlet, action }) => {
    if (action === 'enter') {
        if (outlet.id === 'my-outlet') {
            // do something, perhaps fetch data or set state
        }
    }
});

Router Context Injection

RouterInjector 模块导出一个帮助函数 registerRouterInjector,它组合了 Router 实例的实例化,注册 router 配置信息和为提供的 registry 定义注入器,然后返回 router 实例。

import { Registry } from '@dojo/framework/widget-core/Registry';
import { registerRouterInjector } from '@dojo/framework/routing/RoutingInjector';

const registry = new Registry();
const router = registerRouterInjector(config, registry);

可使用 RouterInjectiorOptions 覆盖默认值:

import { Registry } from '@dojo/framework/widget-core/Registry';
import { registerRouterInjector } from '@dojo/framework/routing/RoutingInjector';
import { MemoryHistory } from './history/MemoryHistory';

const registry = new Registry();
const history = new MemoryHistory();

const router = registerRouterInjector(config, registry, { history, key: 'custom-router-key' });

Outlets

路由集成的一个基本概念是 outlet,它是与注册的应用程序 route 关联的唯一标识符。Outlet 是一个标准的 dojo 部件,可在应用程序的任何地方使用。Outlet 部件有一个精简的 API:

  • id: 匹配时执行 renderer 的 outlet 标识。
  • renderer: 当 outlet 匹配时调用的渲染函数。
  • routerKey (可选): 在 registry 中定义路由时使用的 key - 默认为 router

接收渲染的 outlet 名称和一个 renderer 函数,当 outlet 匹配时,该函数返回要渲染的 DNode

render() {
    return v('div', [
        w(Outlet, { id: 'my-outlet', renderer: () => {
            return w(MyWidget, {});
        }})
    ])
}

可为 renderer 函数传入 MatchDetails 参数,该参数提供路由专有信息,用于确定要渲染的内容和计算传入部件的属性值。

interface MatchDetails {
    /**
     * Query params from the matching route for the outlet
     */
    queryParams: Params;

    /**
     * Params from the matching route for the outlet
     */
    params: Params;

    /**
     * Match type of the route for the outlet, either `index`, `partial` or `error`
     */
    type: MatchType;

    /**
     * The router instance
     */
    router: RouterInterface;

    /**
     * Function returns true if the outlet match was an `error` type
     */
    isError(): boolean;

    /**
     * Function returns true if the outlet match was an `index` type
     */
    isExact(): boolean;
}
render() {
    return v('div', [
        w(Outlet, { id: 'my-outlet', renderer: (matchDetails: MatchDetails) => {
            if (matchDetails.isError()) {
                return w(ErrorWidget, {});
            }
            if (matchDetails.isExact()) {
                return w(IndexWidget, { id: matchDetails.params.id });
            }
            return w(OtherWidget, { id: matchDetails.params.id });
        }})
    ])
}

Global Error Outlet

只要注册了一个 error 匹配类型,就会自动为匹配的 outlet 添加一个全局 outlet,名为 errorOutlet。这个 outlet 用于为任何未知的路由渲染一个部件。

render() {
    return w(Outlet, {
        id: 'errorOutlet',
        renderer: (matchDetails: MatchDetails) => {
            return w(ErrorWidget, properties);
        }
    });
}

Link

Link 组件是对 DOM 节点 a 的封装,允许用户为创建的链接指定一个 outlet。也可以通过将 isOutlet 属性值设置为 false 来使用静态路由。

如果生成的链接需要指定在 route 中不存在的路径或查询参数,可使用 params 属性传入。

import { Link } from '@dojo/framework/routing/Link';

render() {
    return v('div', [
        w(Link, { to: 'foo', params: { foo: 'bar' }}, [ 'Link Text' ]),
        w(Link, { to: '#/static-route', isOutlet: false, [ 'Other Link Text' ])
    ]);
}

所有标准的 VNodeProperties 都可用于 Link 组件,因为最终是使用 @dojo/framework/widget-core 中的 v() 来创建一个 a 元素。

ActiveLink

ActiveLink 组件是对 Link 组件的封装,如果链接处于激活状态,则可以为 a 节点设置样式类。

import { ActiveLink } from '@dojo/framework/routing/ActiveLink';

render() {
    return v('div', [
        w(ActiveLink, { to: 'foo', params: { foo: 'bar' }, activeClasses: [ 'link-active' ]}, [ 'Link Text' ])
    ]);
}

转载于:https://blog.51cto.com/14193089/2348792

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:【Qt系列】之Qt之打包发布

下一篇:Quadtrees UVA - 297

您可能感兴趣

  • .NET Core:通过Web API进行微服务交互

    目录 介绍 命名协议 MicroCommerce应用程序结构 MicroCommerce应用开发 1.接口项目,微服务接口和模型类 2. ProductCatalog项目 3. ShoppingCart项目 4. ActivityLogger项目 5. WebUI项目,用户界面 6.关于通用功能的几句话 应用测试 结论 缺点 下载源代码26.3 KB 介绍 几乎所有在.NET Core中使用...

  • OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)

    介绍 OpenCV+Python 使用OpenCV构建图像识别算法,识别图片中的米粒个数,并计算米粒的平均面积和长度 软件架构 模块:OpenCV 4.0.0.21 编程语言:Python 3.7.2 编译器:PyCharm 2018 程序设计思路 首先介绍一下程序设计的思路: 图像采集(取到图像):可以用摄像头拍摄或者图片直接导入 图像预处理:对图像进行灰度化 基于灰度的阈值分割:使用局部...

  • 多线程基础例题

    通常使用锁方法(Synchronized修饰方法)、锁代码块(Synchronized块)、信号量(Semaphore)、Lock锁 1、要求线程a执行完才开始线程b, 线程b执行完才开始主线程 思路:由题意可知会有两条副线程a和b,编写好a,b的内容后,在主线程中启动两个线程。 关键点在于,一旦开启线程,线程的执行完全是由各自抢占cpu的能力而定,是人为不可控的,为了实现题目中的要求,我们...

  • Kotlin学习之协程

    协程是什么? 一个线程框架,其实就是一套由Kotlin官方提供的线程API。就像 Java 中的 Executor 和 Android 中的 AsyncTask,Kotlin 中的协程也有对 Thread API 的封装,让我们可以在写代码时,不用关注多线程就能够很方便地写出并发操作。 协程好在哪里? 方便。可以在同一个代码块里进行多次的线程切换。 协程最常用的功能是并发,而并发的典型场景就...

  • IntellIJ IDEA2020新功能

    一、java 1、Java 14支持:记录和模式匹配 IntelliJ IDEA 2020.1添加了对Java 14及其新功能的支持。IDE不仅添加了对Records的完整代码洞察支持,而且还使您能够快速创建新记录并生成其构造函数和组件,并警告存在的错误。您还将发现对instanceof运算符的模式匹配的支持,包括新的检查和快速修复,该快速修复通过用新的简洁模式变量替换它们来快速简化冗长的i...

  • SpringMVC学习--响应Ajax请求

    1.首先在webapp下新建一个js目录并导入jquery-3.5.1.min.js,然后在jsp页面中引入jquery Title 2.因为DispatcherServlet会拦截到所有的资源,导致我们的静态资源(img,css,js)也会被拦截,从而不能被使用,解决的方式就是配置静态资源不被拦截,在springmvc.xml中添加以下配置用来告诉DispatcherSe...

  • 前端路 - Webpack

    概述 本质 JavaScript 应用程序的静态模块打包器 核心 加载器(Loader)机制 工作流程 配置初始化 webpack 会首先读取配置文件,执行默认配置 编译前准备 webpack 会实例化 compiler,注册 plugins、resolverFactory、hooks。 reslove 前准备 webpack 实例化 compilation、NormalModuleFact...

  • 浅层砂过滤器(浅层介质过滤器)介绍及现场案例反馈图(多图)

    浅层砂过滤器(浅层介质过滤器)是由多个标准高速砂缸单元组成,其内部设有D特的布水器和集水器,拥有的双向自动冲洗阀,可实现在正常系统运行中多个标准高速砂缸逐个单独的反冲洗,全自动程序控制。具有反冲洗用水量小,设备安装方便,易于操作等优点。该设备流量大,无需维护。根据不同的用户要求,有立式和卧式两个系列。适用于工业和民用循环水系统的水质处理。 【浅层砂过滤器(浅层介质过滤器)工作原理】 浅层砂过...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。