SPA的成功离开不这三个东西,分层架构,路由系统,储存系统。分层架构是我们组织复杂代码的关键,这里特指MVVM的avalon;路由系统是将多个页面压缩在一个页面的关键;储存系统特指本地储存,是安全保存大量数据的关键。本章节介绍的是avalon三柱臣之一的mmRouter(内含mmHistory)。

我们先上一个示例吧。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>路由系统</title>
<script src="avalon.js"></script>
<script>
require(["mmRouter"], function() {
var model = avalon.define({
$id: "test",
currPath: "",
params: {},
query: {},
args: "[]"
})
function callback() {
model.currPath = this.path
var params = this.params
if ("time" in params) {
params.time = avalon.filters.date(params.time, "yyyy年M月dd日")
}
model.params = params
model.args = "[" + [].slice.call(arguments).join(",") + "]"
model.query = this.query
}
avalon.router.get("/aaa/", callback)
avalon.router.get("/bbb", callback)
avalon.router.get("/ccc/:ccc", callback)
avalon.router.get("/ddd/{time:date}/", callback)
avalon.router.get("/eee/{count:\\d{4}}/", callback)
avalon.router.get("/fff", callback)
avalon.history.start({
basepath: "/avalon"
})
avalon.scan()
})
</script>
</head>
<body >
<div ms-controller="test">
<table width="100%" height="300">
<tr>
<td width="250">
<ul>
<li><a href="#!/aaa">aaa</a></li>
<li><a href="#!/bbb?uu=3445345&were=4324">bbb</a></li>
<li><a href="#!/ccc/etretr">ccc</a></li>
<li><a href="#!/ddd/2014-09-19">ddd</a></li>
<li><a href="#!/eee/2222">eee</a></li>
<li><a href="#!/fff?a=1&nn=4&dfg=676">fff</a></li>
</ul>
</td>
<td>
<div style="color:red">this.path: {{currPath}}</div>
<div style="color:blue">arguments: {{args}}</div>
<fieldset>
<legend>this.params</legend>
<ol>
<li ms-repeat="params"> {{$key}}: {{$val}}</li>
</ol>
</fieldset>
<fieldset>
<legend>this.query</legend>
<ol>
<li ms-repeat="query"> {{$key}}: {{$val}}</li>
</ol>
</fieldset>
</td>
</tr>
</table>
<div style="height: 600px;width:1px;"> </div>
<p id="eee">会定位到这里</p>
</div> </body>
</html>

眼见为实,可以看到mmRouter很好地在IE6下运行,对于高版本的浏览器更不在话下。回退按钮,hash如果与页面上的某个锚记同名,它也会自动定拉到那里去。

我们接着详细介绍一下它的用法吧。

  1. 先引入mmRouter(请将mmRouter.jsmmHistory.js这两个文件与avalon.js放在一起)
  2. 定义VM
  3. 定义路由规则
  4. 启动历史管理器
  5. 开始扫描

mmHistory是用于历史管理,它会劫持页面上所有点击链接的行为,当这些链接是以#/#!/开头,就尝试匹配路由规则,阻止页面刷新(通过hash方式或HTML5的replaceState方式)。mmRouter是给我们定义路由规则,路由规则可以更精细地指定每个参数(param)的匹配规则,如果符合就执行对应的回调,如果不符合,就进入error回调。

当用户点击页面链接时,路址栏会发生变化,avalon是参考了angular的方式来处理路址栏。

  • Hashbang模式(默认), 这个模式下所有浏览器都支持
  • HTML5模式, 这个只能应用于firefox, chrome, safari,IE10+,如果浏览器不支持此特性,即使你设置avalon.history.start({html5Mode:true}),它也是在Hashbang模式下运行。

当我们使用history API mode的时候,我们对于不同的浏览器,需要不同的链接, 但我们只需要提供其hash部分就行了,例如<a href=“#/aaa”>link</a>

当用户单击这个超链接时:

  • 在Hashbang mode中,URL会改为/index.html#!/aaa
  • 在HTML5 mode中,URL会改为/index.html/aaa

你会发现,Hashbang mode中的#!后面的部分等于HTML5 mode中的除域名外的所有部分。而#!其实是google的 _escaped_fragment_ 爬抓规则, 方便我们的AJAX应用也能被爬虫收录。当然,我们还需要在head标签内添加一个meta标签:

<meta name="fragment" content="!" />

想了解更多关于这个技术的信息,可以查看这里
下面是路由器的API列表:

  • avalon.history.start(opts), 开始监听URL变化,opts。
  • avalon.history.stop(), 中止监听URL变化。
  • avalon.router.get(path, callback),用于添加路由规则。第一个为路由规则,如"/aaa",
    "/bbb/:bbbId","/eee/{eeeId}/ddd/{dddId:[0-9]{6}}" 冒号后的东西或花括号的东西表示为参数,花括号模式下还可以指定匹配规则。callback为回调函数,框架会将冒号后的或花括中的匹配内容传进来,此外this对象,包含了path、 params、 query等对象与属性。
  • avalon.router.add(method, path, callback) , 添加回调,第一个为请求类型,如GET,POST,DELETE什么, 第2个为路由规则,第3个为回调函数
  • avalon.router.error(callback),如果没有一条路由规则满足此请求,那么就转交此回调处理,我们可以在里面写跳转到404页面这样的逻辑
  • avalon.router.navigate(path),强制触发对应路径的回调
  • avalon.router.setLastPath(path) , 这是框架自己调用,保存最近一次跳转的路径
  • *avalon.router.getLastPath() *,取得最近一次跳转的路径,比如用户F5强制页面,你在ready回调中执行此方法,得到path,然后将它放进navigate中就能回到原来的页面了。

最后我们再详细介绍一下路由规则,它是一个字符串,必须以/开头,它可以在每个/后直接接冒号,表示这之后到下一个斜线或末尾是一个参数。它也可以使用花括号表示里面的内容也一个参数。斜钱风格是来自backbone与express的,花括号风格是来自ui-router。花括号风格更为强大些,因此它可以指定更详细的匹配规则。

avalon.router.get("/ddd/:dddID/",callback)
avalon.router.get("/ddd/{dddID}/",callback)
avalon.router.get("/ddd/{dddID:[0-9]{4}}/",callback)
avalon.router.get("/ddd/{dddID:int}/",callback)

mmRouter默认有四个参数匹配器,分别叫做date, init, bool, string。

      $types: {
date: {
pattern: "[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])",
decode: function(val) {
return new Date(val.replace(/\-/g,"/"))
}
},
string: {
pattern: "[^\/]*"
},
bool: {
decode: function(val) {
return parseInt(val, 10) === 0 ? false : true;
},
pattern: "0|1"
},
int: {
decode: function(val) {
return parseInt(val, 10);
},
pattern: "\d+"
}
}

decode方法是用来将我们从地址栏抽取出来的那些小字符串转换为想要的类型或格式。如果你想要更多效果,还可以自己添加,如avalon.router.$type.d4 = { pattern: ’[0-9]{4}’, decode: Number}

 avalon.router.get("/ddd/{dddID:d4}/",callback)

总而言之,mmRouter是远远比angular自带路由器与backbone那个强大N多。未来还会进一步开发类似ui-router那样基于状态管理的路由器,敬请期待!

迷你MVVM框架 avalonjs 学习教程20、路由系统的更多相关文章

  1. 迷你MVVM框架 avalonjs 学习教程19、avalon历史回顾

    avalon最早发布于2012.09.15,当时还只是mass Framework的一个模块,当时为了解决视图与JS代码的分耦,参考knockout开发出来. 它的依赖收集机制,视图扫描,绑定的命名d ...

  2. 迷你MVVM框架 avalonjs 学习教程18、一步步做一个todoMVC

    大凡出名的MVC,MVVM框架都有todo例子,我们也搞一下看看avalon是否这么便宜. 我们先从react的todo例子中扒一下HTML与CSS用用. <!doctype html> ...

  3. 迷你MVVM框架 avalonjs 学习教程3、绑定属性与扫描机制

    在MVVM框架中,你都会看到页面定了许多奇怪的属性,比如knockout的data-☆,angular的ng-☆,avalon的ms-☆,此外还有一些只写文本节点上的双花括号,它们统称为指令.ms-☆ ...

  4. 迷你MVVM框架 avalonjs 学习教程1、引入avalon

    avalon是国内最强大的MVVM框架,没有之一,虽然淘宝KISSY团队也搞了两个MVVM框架,但都无疾而终.其他的MVVM框架都没几个.也只有外国人与像我这样闲的架构师才有时间钻研这东西.我很早之前 ...

  5. 迷你MVVM框架 avalonjs 学习教程16、过滤器

    avalon的过滤器是参考自angular与rivets.它也被称做管道文本过滤器,它的处理对象只能是文本(字符串),它只能用在文本绑定中,并且只能是双花括号形式.下面是各大家的过滤器比较: rive ...

  6. 迷你MVVM框架 avalonjs 学习教程11、循环操作

    avalon是通过ms-repeat实现对一组数据的批量输出.这一组数据可以是一个数组,也可以是一个哈希(或叫对象).我们先从数组说起吧. 第二节就说,凡是定义在VM中的数组,如果没有以$开头或者没放 ...

  7. 迷你MVVM框架 avalonjs 学习教程4、数据填充

    MVVM是前端的究极解决方案,你们可能用过jQuery,但那个写的代码不易维护:你们可以听过说requirejs与seajs,传说中的模块开发,加载器,但它们的最终目标是打包:你们可能听过unders ...

  8. 迷你MVVM框架 avalonjs 学习教程2、模块化、ViewModel、作用域

    一个项目是由许多人分工写的,因此必须要合理地拆散,于是有了模块化.体现在工作上,PM通常它这为某某版块,某某频道,某某页面.某一个模块,必须是包含其固有的数据,样式,HTML与处理逻辑.在jQuery ...

  9. 迷你MVVM框架 avalonjs 学习教程22、avalon性能大揭密

    avalon之所以能在页面处理1W个绑定(angular对应的数字是2000),出于两个重要设计--基于事件驱动的双向绑定链及智能CG回收机制. avalon的双向绑定链是通过Object.defin ...

随机推荐

  1. LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治

    题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...

  2. php设计模式之职责链模式

    <?php /** * @desc php设计模式之职责链模式(责任链模式) 定义:顾名思义,责任链模式为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这 ...

  3. php提交表单校验例子

    <!DOCTYPE HTML> <meta http-equiv="Content-Type" content="text/html; charset= ...

  4. SpringMVC 实现返回一段数据 & 实现自动发送json格式数据 - AJAX

    实现返回一段数据 - AJAX 当页面通过AJAX来访问Controller时,期望得到的不是一个页面而是一段数据,此时可以使用如下方法,直接向相应中写入数据: /** * 直接向响应中写出数据,通常 ...

  5. 关于Linux DNS部分处理

    如果不能ping 通外网地址进行解析的话进行如下处理

  6. 1076 Forwards on Weibo (30 分)

    1076 Forwards on Weibo (30 分) Weibo is known as the Chinese version of Twitter. One user on Weibo ma ...

  7. 牛逼的lsof命令!!!

    linux lsof命令详解 简介 lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访 ...

  8. 【Codeforces】CF 467 C George and Job(dp)

    题目 传送门:QWQ 分析 dp基础题. $ dp[i][j] $表示前i个数分成j组的最大和. 转移显然. 吐槽:做cf题全靠洛谷翻译苟活. 代码 #include <bits/stdc++. ...

  9. 网络文件系统与 Linux

    网络文件系统 是文件系统之上的一个网络抽象,来允许远程客户端以与本地文件系统类似的方式,来通过网络进行访问.虽然 NFS 不是第一个此类系统,但是它已经发展并演变成 UNIX® 系统中最强大最广泛使用 ...

  10. c++官方文档

    来自官方文档...感谢老王指出需要c++11,一下代码全在c++11下编译,编译参数加入  -std=c++11 #include<stdio.h> #include<iostrea ...