director.js:客户端的路由---简明中文教程

1、引子

  最近学用director.js,那是相当的简单易学易使用。不过开始学的时候,搜搜过后,却没有发现相关的中文教程。于是决定硬啃E文,翻译备用的同时也当是给自己上课并加深对它的理解。

  director.js 的官方地址请点击 这里 查看,本教程内容也主要来自于这里。

2、director.js是什么

  director.js 按照我的理解就是客户端的路由注册/解析器,它在不刷新页面的情况下,利用“#”符号组织不同的URL路径,并根据不同的URL路径来匹配不同的回调方法。通俗点说就是什么样的路径干什么样的事情。

  director.js 适用于客户端浏览器以及node.js的服务器端应用,在两者的应用场景里调用方法仅有少量的不同。它非常适合用来开发不需要刷新的单页程序以及node.js应用。尤其单页程序,对于不想介入手机APP开发的同学,可以利用这个实现类似APP的应用程序。

  director.js 不依赖于任何其他的js库,例如jquery等。但是它又和jquery能很好的融合在一起进行使用。

  在本篇主要学习它在客户端的应用,node.js服务器端暂不讨论。

  

3、简单的开始

  上文简单提到: director.js 是通过“#”符号进行路径组织的,例如:

http://www.demo.com/#/showhttp://www.demo.com/#/show/listhttp://www.demo.com/#/show/single

  

  路由注册在URL里的体现是用“#”符号来标识路由的开始,再利用"/"分隔符(分隔符可自定义,后面会讲到)来定义路由片段。客户端路由其实就是通过URL来区分应用程序的不同状态,并且定义在不同的状态下应该做什么事情。当用户访问不同的URL时,director.js 会解析路由信息并告知应用程序需要做什么事情。

  路由格式具体可参考下图:

  下面是一个简单的例子:

<html>
  <head>
    <title>A Gentle Introduction</title>
    <script src="/js/director.min.js"></script>
    <script>

      var author = function () { console.log("author"); },
          books = function () { console.log("books"); },
          viewBook = function(bookId) { console.log("viewBook: bookId is populated: " + bookId); };

      var routes = {
        ‘/author‘: author,
        ‘/books‘: [books, function() { console.log("An inline route handler."); }],
        ‘/books/view/:bookId‘: viewBook
      };

      var router = Router(routes);
      router.init();

    </script>
  </head>
  <body>
    <ul>
      <li><a href="#/author">#/author</a></li>
      <li><a href="#/books">#/books</a></li>
      <li><a href="#/books/view/1">#/books/view/1</a></li>
    </ul>
  </body>
</html>

  

  和jquery一起使用的列子:

<html>
  <head>
    <meta charset="utf-8">
    <title>A Gentle Introduction 2</title>
    <script src="/js/jquery.min.js"></script>
    <script src="/js/director.min.js"></script>
    <script>
    $(‘document‘).ready(function(){
      var showAuthorInfo = function () { console.log("showAuthorInfo"); },
          listBooks = function () { console.log("listBooks"); },
          allroutes = function() {
            var route = window.location.hash.slice(2),
                sections = $(‘section‘),
                section;
            if ((section = sections.filter(‘[data-route=‘ + route + ‘]‘)).length) {
              sections.hide(250);
              section.show(250);
            }
          };

      var routes = {
        ‘/author‘: showAuthorInfo,
        ‘/books‘: listBooks
      };

      var router = Router(routes);

      router.configure({
        on: allroutes
      });
      router.init();
    });
    </script>
  </head>
  <body>
    <section data-route="author">Author Name</section>
    <section data-route="books">Book1, Book2, Book3</section>
    <ul>
      <li><a href="#/author">#/author</a></li>
      <li><a href="#/books">#/books</a></li>
    </ul>
  </body>
</html>

  下面将会就director.js 客户端相关的API进行详细的说明。

4、初始化及路由注册

  director.js 的主要对象是Router对象,构造方法如下:

var router = new Router(routes);

  

  构造方法中传入的routes参数是一个路由表对象,它是一个具有键值对结构的对象,路由允许多层的嵌套定义。

  键值对的键对应URL中传入的路径,一般一个键对应按分隔符切割后的某一部分;而键值对的值则对应该路径需要触发的回调函数名,可以传入一个或多个函数名,传入多个函数名时请使用数组对象。一般来说,回调函数要在路由表对象使用前先声明,否则js会报错。

  另外,回调函数除非特殊情况,一般不推荐使用匿名函数,请尽量先声明后使用。

  var routes = {
    ‘/dog‘: bark,
    ‘/cat‘: [meow, scratch]
  };

  上面例子中,对应的URL分别为:#/dog 和 #/cat

  

  声明Router对象后,需要调用init()方法进行初始化,如下:

var routes = {
    ‘/dog‘: bark,
    ‘/cat‘: [meow, scratch]
};

var router = Router(routes);
router.init();

5、路由的即时注册

  当我们在开发一些规模比较大的应用的时候,一般做不到一开始就将需要的路径和它对应的回调函数都预先准备好。很多时候,我们都是在做到某一功能时,或者是开发一些独立性比较强耦合度比较低的模块时,才知道我们需要什么样的路径和回调函数。这个时候我们就需要实时注册路由的功能了。

  director.js 通过“on”方法,提供对即时注册功能的支持,示例如下:

var router = Router(routes).init();
....
router.on(‘/rabbit‘, function(){
  ...
})

6、路由事件

  路由事件是路由注册表中一个有固定命名的属性,是指当路由方法router.dispatch()被调用时,路由匹配成功的时定义的需要触发的回调方法(允许定义多个回调方法)。上文即时注册功能里的"on"方法就是一个事件。具体信息如下:  

  • on :当路由匹配成功后,需要执行的方法
  • before:在触发“on”方法之前执行的方法

  仅在客户端有效的方法:

  • after:当离开当前注册路径时,需要执行的方法
  • once: 当前注册路径仅执行一次的方法
var routes = {
      "/about/:id": {
            before: function (id) { alert("direct to : /Home/About/" + id); },
            on: function (id) { window.location = "/Home/About/" + id; }
};

  *以上示例中使用了匿名函数,仅因为做为示例比较方便,不推荐这种使用方式

7、配置参数

  director.js 通过配置一些可选项的参数从而提升Router对象的灵活性。而这些参数的设置需要通过router.configure()方法实现。

var router = new director.Router(routes).configure(options);

  具体的配置参数有:

  • recurse:控制路由递归触发方式的参数,可选值为"forward","backward"和"false",客户端的默认值是"false",而服务端的默认值是"backward"
  • strict:当值为"false"时,路径允许以"/"结尾(也可以是其他自定义的分隔符);默认值是"true",说明默认不允许路径以"/"结尾
  • async:同步异步控制器,值为"ture","false",默认值为"false"
  • delimiter:路由分隔符,默认值为"/"
  • notfound:当路由方法router.dispatch()被调用时,没有匹配到任何路由时触发的方法
  • on:当路由方法router.dispatch()被调用时,任何一个路由匹配成功后都需要执行的方法;与上文路由事件中的“on”事件的区别类似于全局和局部的概念,路由表中仅针对当前注册的路由;而configure方法中的"on"则针对全局的所有路由
  • before:当路由方法router.dispatch()被调用时,当任何一个路由匹配成功并在"on"执行之前需要执行的方法;与上文路由事件中的 “before” 事件的区别同上

  仅在客户端有效的参数:

  • resource:用来进行回调函数绑定的基于字符串的对象。使用该参数能实现回调函数的延迟绑定(原词是 "late-binding",后面有相关的详细说明)
  • after:当给定的路径不再是当前激活的路径时触发的方法,可以理解为离开当前路径后触发的方法;与上文路由事件中的 “after” 事件的区别同上

  *以上的配置参数在后面均有详细的讲解

  *另外仅在客户端起效的参数还有html5history和run_handler_in_init,这两个参数是与html5相关,暂时也不讨论

8、URL匹配

  在路由事件那一节的示例里,有这么一个路由表达式"/about/:id",其中":"后面定义的部分表示实际路径对应的这部分是传入回调函数的参数,例如"#/about/5"中,5就是id参数的值。参数的匹配还可以用嵌套的方式来定义:

var router = Router({
  ‘/about‘: {
    ‘/:id‘: {
      on: function (id) { console.log(id) }
    }
  }
});

  在实际应用的过程中,我们的路由可能会变得非常复杂,像"/about/:id"这样简单的表达式并不能满足我们的需求。而director.js 支持利用正则表达式来匹配复杂的路由名称,匹配到的值会作为参数传给回调函数,例如:

var router = Router({
  ‘/hello‘: {
     ‘/(\\w+)‘: {
      on: function (who) { console.log(who) }
    }
  }
});

  当URL传入‘#/hello/world‘,则回调函数的who=world

  支持更为复杂的多参数的传递:

var router = Router({
  ‘/hello‘: {
    ‘/world/?([^\/]*)\/([^\/]*)/?‘: function (a, b) {
      console.log(a, b);
    }
  }
});

  当URL传入‘#/hello/world/johny/appleseed‘,则回调函数的a=johny,b=applesee

9、路由的递归匹配

  全局配置中的recurse参数决定了路径在路由表中的命中方式以及命中顺序。命中方式包括递归命中和精确命中;命中顺序包括正序,反序和中断。

  当参数设定为“forward、backward”时,表明路由的命中方式是递归命中,并按照规定的顺序命中,forward为正序,backward为反序。路由如果定义了多个路由片段,则它们对应的回调函数均可命中,也就是说一个路径可以命中多个函数。

  当没有特别指定该参数的值时(即默认值"false"),则标明路由的命中方式为精确命中,需要完全匹配整个路径后才可以命中,也就是说一个路径只能命中一个函数。

  当URL传入"#/dog/angry"时,路由表注册如下:

  var routes = {
    ‘/dog‘: {
      ‘/angry‘: {
        on: growl
      },
      on: bark
    }
  };

  

  当没有指定递归匹配的方式时,仅命中growl方法。

  当指定递归匹配参数的值为backward时,首先命中growl方法,然后再命中bark方法,按照路径的注册顺序反序命中。如下:

var router = Router(routes).configure({ recurse: ‘backward‘ });

  当指定递归匹配参数的值为forward时,首先命中bark方法,然后再命中growl方法,按照路径的注册顺序正序命中。如下:

var router = Router(routes).configure({ recurse: ‘forward‘ });

  当指定了递归匹配参数后,如果命中的函数中使用了"return false;"的语句返回,则会中断递归命中,直接返回。如下:

  var routes = {
    ‘/dog‘: {
      ‘/angry‘: {
        on: function() { return false; }
      },
      on: bark
    }
  };
  var router = Router(routes).configure({ recurse: ‘backward‘ });

  无中断时,首先会命中angry下的方法,然后命中bark方法;但是在使用return false语句之后,执行完angry命中的方法后将不再递归命中别的方法(bark)。

10、资源参数

  全局配置中的resource参数仅在客户端应用中可用,它是一个文本对象,其中的文本属性值主要用来定义路由匹配命中后的回调方法名。它可以为程序提供更好的封装性,以便更好的进行结构设计。

  var router = Router({
    ‘/hello‘: {
      ‘/usa‘: ‘americas‘,
      ‘/china‘: ‘asia‘
    }
  }).configure({ resource: container }).init();

  var container = {
    americas: function() { return true; },
    china: function() { return true; }
  };

  示例中,container对象定义在路由对象之后,我觉得这个就是之前说的“延迟绑定”功能。因为路由的回调函数绑定必须遵守先声明后使用的方法,这个示例明显是先使用后声明。但是我测试了一下,这样做会报错,还是不能改变先声明后使用的顺序。因此延迟绑定的意思我还没真正搞清楚。

11、小结

  director.js 在客户端应用的中文简明教程暂时就是这些,有了这些知识做一个简单的CRUD的DEMO程序是完全没问题了。不过我在做这个DEMO的过程中,觉得还是没有体会到director.js 使用的精髓。因为我在命中后调用了AJAX方法,我的问题是既然已经用了AJAX方法,由何必用director.js 呢?感觉还是得再详细看一下《bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序》这篇文章和它的示例才能体会director.js 的精髓。也感谢该文章作者的分享。

  以后有时间再研究和补齐服务端应用的教程,以及在html5应用下的几个配置参数和方法。需要了解更详细信息的同学还是可以去它的 官方地址 啃E文。

时间: 2024-12-11 11:46:33

director.js:客户端的路由---简明中文教程的相关文章

director.js实现前端路由

注:director.js的官网 [https://github.com/flatiron/director] director.js是什么? 理解:前端的route框架,director.js客户端的路由注册/解析器,在不刷新的情况下,利用“#”号组织不同的URL路径,并根据不同的URL路径进行不同的方法调用.意思就是有什么样的路径就有什么样的方法. 场合:客户端浏览器和node.js的服务器应用.非常适合用来开发不需要刷新的单页面应用程序以及node.js应用. 兼容性:不依赖与任何库.例如

director.js 支持中文路径

1.director.js 支持中文路径 390行 return mod === str ? "([._a-zA-Z0-9-%()]+)" : mod; 修改正则 return mod === str ? "([._a-zA-Z0-9-%()]+|[\u4E00-\u9FFF]+)" : mod; 2.ie8bug (1)不支持isArray方法文件头加上 if (!Array.isArray) { Array.isArray = function(arg) { r

jQuery.qrcode.js客户端生成二维码,支持中文并且可以生成LOGO

描述: jquery.qrcode.js 是一个能够在客户端生成矩阵二维码QRCode 的jquery插件 ,使用它可以很方便的在页面上生成二维条码.此插件是能够独立使用的,体积也比较                 小,使用gzip压缩后才不到4kb.因为它是直接在客户端生成的条码, 所以不会有图片下载的过程,能够实现快速生成.它是基于一个多语言的类库封装的,也不依赖于其他额外的服务. 好处:使用jquery-qrcode的好处,不需要在服务器端生成多余的二维码图片,二维码直接通过JavaSc

webstorm的中文教程和技巧分享

webstorm是一款前端javascript开发编辑的神器,此文介绍webstorm的中文教程和技巧分享. webstorm8.0.3中文汉化版下载:百度网盘下载:http://pan.baidu.com/s/1pJI9PMV WebStorm为前端javascript开发而生,专门为 javascript开发做了很多优化,令前端工程师眼前一亮的. 一.webstorm的功能 1.webstorm的智能的代码补全: 支持不同浏览器的提示,还包括所有用户自定义的函数(项目中) 代码补全包含了所有

简明 Python 教程中的第一个备份脚本

第一次学习python写的脚本 原为简明 Python 教程中的第一个脚本 原脚本如下 #!/usr/bin/python # Filename: backup_ver1.py import os import time # 1. The files and directories to be backed up are specified in a list. source = ['/home/swaroop/byte', '/home/swaroop/bin'] # If you are u

Netty4.x中文教程系列(二) Hello World !&lt;转&gt;

在中国程序界.我们都是学着Hello World !慢慢成长起来的.逐渐从一无所知到熟悉精通的. 第二章就从Hello World 开始讲述Netty的中文教程. 首先创建一个Java项目.引入一个Netty 框架的包.这个步骤我在本系列教程的后面就不在重复了. 先上一张我示例的项目工程图给大家看一下: 1.下载并为项目添加Netty框架 Netty的包大家可以从Netty官网:http://netty.io/downloads.html 下载 如图所示: Netty提供了三个主要版本的框架包给

Netty4.x中文教程系列(六) 从头开始Bootstrap

Netty4.x中文教程系列(六) 从头开始Bootstrap 其实自从中文教程系列(五)一直不知道自己到底想些什么.加上忙着工作上出现了一些问题.本来想就这么放弃维护了.没想到有朋友和我说百度搜索推荐了我的文章.瞬间有点小激动啊.决定自己要把这个教程系列完善下去.这里诚挚的想支持我的盆友们道歉.真的是让你们失望了.我居然有想放弃的这种丧心病狂的念头.以后绝对不会了. 其实伴随着对Netty的逐步深入学习.感觉自己对netty的了解仍然有所欠缺.加上笔者语文课是美术老师教的.所以..说多了都是泪

SWFObject使用方法和中文教程及IE无法加载播放的问题

SWFObject使用方法和中文教程 SWFObject的使用是非常简单的,只需要包含 swfobject.js这个js文件,然后在DOM中插入一些简单的JS代码,就能嵌入Flash媒体资源了. 下面是一个最简单的范例: 1.文件顶部需加载swfobject.js <script type="text/javascript" src="swfobject.js"></script> <script type="text/jav

ionic中文教程

ionic(ionic framework)是款接近原生的Html5移动App开发框架,会html css js就可以开发app,创建精彩的手机app应用,从ionic中文教程开始. 利用熟悉的技术(html5 css js)不需要重新再学习新技术,采用原有的web技术就可以创建跨平台的移动app. ionic 是目前最具潜力的一款 HTML5 手机应用混合开发开发框架.通过 SASS 构建应用程序,它提供了通用的 UI 标签和css样式风格来帮助开发者开发强大的应用.ionic使用 JavaS