Dojo 路由

路由

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' ])
    ]);
}

原文地址:http://blog.51cto.com/14193089/2348792

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易知道用户保存了什么,我希望当用户第一次看到网格时,网格处于不可编辑状态.当用户准备好后,他们可以单击编辑按钮,这将使网格的某些部分可编辑.然后,有一个保存或取消按钮可以保存更改或还原.在大多数情况下它是有效的.但
我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以轻松打包为Web,Mobiles和可能的Standalone版本的方式来实现这一目标.我不想使用Flash.因此,我确信(无论如何我会听取建议)使用JavaScript和SVG.我正在对这个问题进行大量研究,但我很难把各个部分放在一起.我知道Raphae
我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部件–我在表单中使用–将固定格式(JavaScript基本格式)的实数值(例如:12.56)设置为HTML表单输入字段(但根据浏览器区域设置显示/编辑它们,所以用户总是看到格式正确的数字).另一方面,Grails期望输入字段根据浏览器
1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforjavaScript的学习历程,本篇将从最开始的arcgisapiforjavaScript部署开始,个人声明:博文不在传道受业解惑,旨在方便日后复习查阅。由于是自学,文章中可能会出现一些纰漏,请留言指出,不必留有情面哦!2.下载ArcGISforDe
我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑:Thedeclarefunctionisdefinedinthedojo/_base/declaremodule.declareacceptsthreearguments:className,superClass,andproperties.ClassNameTheclassNameargumentrepresentsthenameofthec
我的团队由更多的java人员和JavaScript经验丰富组成.我知道这个问题曾多次被问到,但为了弄清楚我的事实,我需要澄清一些事情,因为我在客户端技术方面的经验非常有限.我们决定使用GWT而不是纯JavaScript框架构建我们的解决方案(假设有更多的Java经验).这些是支持我的决定的事实.>
路由dojo/framework/srcouting/README.mdcommitb682b06ace25eea86d190e56dd81042565b35ed1Dojo应用程序的路由路由FeaturesRoute配置路径参数RouterHistoryManagersHashHistoryStateHistoryMemoryHistoryOutletEventRouterContextInjectionOutl
请原谅我的无知,因为我对jquery并不熟悉.是否有dojo.connect()的等价物?我找到了这个解决方案:http:/hink-robot.com/2009/06/hitch-object-oriented-event-handlers-with-jquery/但是没有断开功能!你知道jquery的其他解决方案吗?有jquery.connect但这个插件在我的测试中不起作用.
与java类一样,在dojo里也可以定义constructor 构造函数,在创建一个实例时可以对需要的属性进行初始化。//定义一个类mqsy_yjvar mqsy_yj=declare(null,{     //thedefaultusername    username: "yanjun",          //theconstructor   
我一直在寻找一些最佳实践,并想知道Dojo是否具有框架特定的最佳实践,还是最好只使用通用的Javascript标准?特别是我主要是寻找一些功能和类评论的指导方针?解决方法:对于初学者来说,这是项目的风格指南:DojoStyleGuide
我有’05/17/2010’的价值我想通过使用dojo.date.locale将其作为“2010年5月17日”.我尝试过使用dojo.date.locale.parse,如下所示:x='05/17/2010'varx=dojo.date.locale.parse(x,{datePattern:"MM/dd/yyyy",selector:"date"});alert(x)这并没有给我所需的日期
我正在尝试创建一个包含函数的dojo类,这些函数又调用此类中的其他函数,如下所示:dojo.provide("my.drawing");dojo.declare("my.drawing",null,{constructor:function(/*Object*/args){dojo.safeMixin(this,args);this.container=args[0];
我知道你可以使用jQuery.noConflict为jQuery做这件事.有没有办法与Dojo做类似的事情?解决方法:我相信你可以.有关在页面上运行多个版本的Dojo,请参阅thispage.它很繁琐,但似乎是你正在寻找的东西.一般来说,Dojo和jQuery都非常小心,不会破坏彼此或其他任何人的变量名.
我有一个EnhancedGrid,用户经常使用复杂的过滤器.有没有办法允许用户保存或标记过滤器,以便将来可以轻松地重新应用它?我知道我可以通过编程方式设置过滤器,但我无法预测用户想要的过滤器.谢谢!编辑:自己做了一些进展…使用grid.getFilter()返回过滤器的JSON表示,然后使用json.strin
我有这个代码:dojo.declare("City",null,{constructor:function(cityid,cityinfo){}});dojo.declare("TPolyline",GPolyline,{constructor:function(points,color){},initialize:function(map){});应该是什
我遇到的问题是我的所有javascript错误似乎来自dojo.xd.js或子模块.我正在使用chrome调试器和许多dijit功能,如dijit.declaration和dojo.parser.这有点烦人,因为它很难找到简单的错误或滑倒.我希望我可以添加一个选项,允许我的调试器在我的非dojo代码中显示选项会发生的位置.我是
我正在使用DojoToolkit数字/解析函数来处理格式化和使用ICU模式语法解析字符串.有没有人知道有可能采取任意ICU模式字符串并以某种方式使用Dojo(或其他)库将其分解为它的部分(例如,对于数字模式,它可以被分解为小数位数,数千个分组等…).我希望这样做,而不需要让我的代码密切了
我有两个看似相关的问题,访问在不同的地方定义的javascript函数.我遇到的第一个问题是调用我在firgbug或safari控制台中定义的函数.我定义了一个名为getRed的函数,如下所示:functiongetRed(row,col){//dosomethingstuffandreturntheredvalueasa
我想添加一个在Ajax调用中指定的外部样式表.我已经找到了一种方法来使用jQuery(参见下面的示例),但是我需要使该方法适应dojoJavaScript框架.JQuery示例$('head').append('<linkrel="stylesheet"type="text/css"href="lightbox_stylesheet.css">');谢谢.解决方法:一旦你
我正在尝试使用dojo.connect将onMouseDown事件连接到图像,如:dojo.connect(dojo.byId("workpic"),"onMouseDown",workpicDown);functionworkpicDown(){alert("mousedown");}类似的代码几行后,我将onMouse*事件连接到dojo.body确实完全正常工作.但是当我点击图像时