路由模块(Router)
概述:
Router是一种根据不同URL的来表现的页面状态的能力,基于HTML5 history api实现.
Router模块提供了根据不同组件state、model的states、以及自定义states来实现的对浏览器的前进后退导航、有状态的书签、可分享的URL、URL自定义处理器等支持。如果你曾经使用过一些后端框架比如Express、Sinatra、Play,那么你将会发现和他们的想法非常相似。
为什么要基于客户端的URL路由:
URL是维护一个web app的状态的非常好的方法,因为URL很容易被看到,很容易修改,而且可以被存储为书签和分享。
原本我们在服务端的web框架中使用URL路由技术,来达到根据不同的URL,不同的参数来返回不同的页面,
现在我们可以配合客户端的URL路由技术来达到更好用户体验。
客户端路由能做什么:
如上图,我们可以看到在URL中#!后面的部分是随着页面中组件contents的切换而变化的,这就是前端路由的能力-有状态的URL(URL中会反映出当前页面内的需要关心的状态),同样的如果你手动把URL中的#!content-1 改成#!content-2 你会发现contents是会切换到第二个页面,同时不会有后台请求发送的哦。
这里要注意下:我们可以发现虽然URL变化了,但是并没有发送后端请求,这就是所谓的前端路由,一般情况是随着URL变化,普通的后端路由情况是会重新发送请求获取页面的.
同时如果把这个有状态的URL分享出去,打开这个URL后这个页面同样能定位到相应状态,如下图
这个时候,机智的朋友就会说了,既然手动修改URL能切换到第二个页面,那么我写一个<a href=”#!content-2″/>是不是也能切换到第二个页面?答案是当然,同学你果然机智!这就是我们前端路由模块要支持的能力-支持hashbang写法的链接。
好了,说了这么多估计大家已经明白前端路由大致是个什么东东了把。其实Router模块的实现并不是只有上面例子看起来那么简单。
Router模块有什么:
首先我们看下Router对应的代码主要的的模块文件
- hashbangParser.js
- router.js
- routeState.js
- 如果说组件就是一个状态机,根据不同的状态响应不同的逻辑、展现,那么每个组件可以把自己的状态反映到URL中,但是WeX5的页面是有很多model(可以认为一个.w页面就是一个model) 组合出来的,所以我们认为每个model需要维护当前model下状态的,所有每个model下就有一个对象$routeState.
- model的状态变化了,他有可能是根model(比如在portal中的portal页面),他有可能是子model(比如portal中打开的页面,windowDialog打开的页面等),那么这些状态怎么合并,怎么向上传递,父model收到变化通知要向子model分发,等问题,所以就有了router.js
- 上面说到可能会到复杂的嵌套、组合等情况,那么url毕竟要有一定的复杂度,所以我们需要一个parser用来把复杂的url理解成对象。
Router模块怎么使用:
- 现在支持route的组件有contents和dialog(windowDialog).只需要在设计界面设置组件的routable属性为true,组件默认就可以有路由能力。当然组合嵌套情况默认已经支持,不用担心。
- 如果我有自定义路由的需求怎么办? 参考portal中自定义路由相关代码,来看看他是怎么自定义路由的吧。这里就不详细解释代码了。
Router组件:
route组件提供了自定义自己的路由的能力。
api说明:
addRouteItem :添加路由项 参数:name, param 从上面介绍已知:路由项有三部分组成 xid\name\param 这里xid为route组件的xid ,name、param就是你可以自定以的。 removeRouteItem:删除路由项 参数:name publishState:把当前路由状态发布出去(最终反映到url上) onRoute : 路由变动事件 (回调形事件) event格式如下 {source":"当前组件", "cancel":"false", "xid":"xid", "name":"name", "param":"param", "routeState":"routeState", "async":"false", "dtd":"dtd" } 你可以通过判断 name来只对你关心的状态变化进行处理 routeState 有三种 enter、leave、update 如果你的处理中有异步逻辑 可以设置async为true 然后通过dtd来完成异步处理。