xmlplus 组件设计系列之七 - 路由
在浏览器端,对路由的理解一般是根据不同的 URL 完成页面的切换。在服务器端,则是根据不同的 URL 请求回馈相关的页面。在本章,我们广义的组件路由的定义:根据接收到的不同命令,组件对象呈现出不同的子级页面。在这里将介绍与路由相关的一个组件,即视图栈 ViewStack。

视图栈初步
该组件在《文档》部分的最后一个章节《延迟实例化》已经出现过了。这里将对一些细节部分进行解读。下面再次给出该组件的源码。
// 07-01
ViewStack: {
xml: "<div id='viewstack'/>",
fun: function (sys, items, opts) {
var args, children = this.children(),
table = children.call("hide").hash(),
ptr = table[opts.index] || children[0];
if (ptr) ptr = ptr.trigger("show").show();
this.on("switch", function ( e, to ) {
table = this.children().hash();
if ( !table[to] || table[to] == ptr ) return;
e.stopPropagation();
args = [].slice.call(arguments).slice(2);
ptr.trigger("hide", [to+''].concat(args)).hide();
ptr = table[to].trigger("show", [ptr+''].concat(args)).show();
});
return Object.defineProperty({}, "selected", { get: function() {return ptr;}});
}
}
从静态接口看,该组件允许提供静态参数 index,该参数是组件 ViewStack 某一儿子组件对象的名称,它用于指出哪一个子级组件会被最先呈现。请看下面的示例。
// 07-01
Index: {
xml: `<ViewStack index='bar'>
<button id='foo'>foo</button>
<button id='bar'>bar</button>
</ViewStack>`
}
该示例中,ViewStack 包含一值为 bar 的属性 index,表明组件在实例化时,组件对象 bar 会最先呈现。而默认情况下,该组件的第一个子级组件会作为初始显示对象。再从动态接口看,该组件的函数项导出了一个名为 selected 的只读属性,该属性用于指示当前显示的子级组件对象。
通过事件切换目标组件对象
对于子级组件对象之间切换,该组件的函数项并未导出相关的接口,而是通过接收 switch 事件来完成切换。请看下面的示例。
// 07-02
Index: {
xml: `<ViewStack id='index'>
<button id='foo'>foo</button>
<button id='bar'>bar</button>
</ViewStack>`,
fun: function (sys, items, opts) {
sys.index.on("click", "*", function(e) {
var to = this + '' == "foo" ? "bar" : "foo",
data = "hello, world";
this.trigger("switch", [to, data]);
});
sys.foo.on("show", function (e, prev, data) {
console.log("previous page is " + prev, "from data is " + data);
});
sys.bar.on("hide", function (e, prev, data) {
console.log("previous page is " + prev, "from data is " + data);
});
}
}
对于该示例,当用户点击文字时,文字会在 foo 和 bar 之间切换,也即两个页面之间切换,切换是通过相应子级对象派发 switch 事件进行的。另外,组件 ViewStack 在切换页面时,还会对本次显示的页面派发事件 show,以及对本次隐藏的页面派发事件 hide,相关页面可以根据需要选择侦听与否。并且在侦听函数中,可以获知前一显示页面 ID 以及所传输的相关数据。
动态添加与移除子级对象
组件 ViewStack 支持动态添加与移除子级的组件对象,请看下面的一个示例。
// 07-03
Index: {
xml: `<ViewStack id='index'>
<button id='foo'>foo</button>
</ViewStack>`,
fun: function (sys, items, opts) {
sys.foo.on("click", function () {
var xml = "<button id='bar'>bar</button>";
sys.index.append(xml).trigger("switch", "bar");
});
}
}
该示例中,当用户点击按钮 foo 应用会动态添加了一个子级组件,并且通过派发事件 switch 将当前显示的视图切换为刚新添加的视图。
优化配置
组件 ViewStack 一般配合组件的延迟实例化功能使用。对于一些比较复杂的组件,这样有助于加快显示应用的初始页面。下面做简单示范。
// 07-04
Index: {
xml: `<ViewStack id='index'>
<button id='foo'>foo</button>
<button id='bar'>bar</button>
</ViewStack>`,
map: { defer: "bar" },
fun: function (sys, items, opts) {
sys.foo.on("click", function () {
sys.index.trigger("switch", "bar");
});
}
}
此示例中,ViewStack 子级包含三个子组件,其中组件对象 bar 被设置为需要延迟实例化,只有当视图切换在组件对象 bar 时,它才真正开始实例化。
与 HTML5 History API 的配合使用
这里我们看看如何让组件 ViewStack 与 HTML5 History API 的配合使用。下面是一个简单的例子。
// 07-05
Index: {
xml: "<ViewStack id='index'>\
<button id='foo'>foo</button>\
<button id='bar'>bar</button>\
</ViewStack>",
fun: function (sys, items, opts) {
sys.index.on("show", "button", function (e) {
window.history.pushState({name: this + ""}, null, "/" + this);
});
window.addEventListener("popstate", function (e) {
e.state && sys.index.trigger("switch", e.state.name);
});
sys.foo.on("click", e => sys.foo.trigger("switch", "bar"));
sys.bar.on("click", e => sys.foo.trigger("switch", "foo"));
}
}
该示例的关键点在于,当视图栈组件对象的子级页面发生变更时,使用函数 pushState 记录下来;另外需要侦听浏览器的 popstate 事件,当用户点击「前进」、「后退」按钮时,完成相应页面的切换。这种技术非常适合在单页应用中完成无刷新跳转,可以给用户带来非常好的体验。
xmlplus 组件设计系列之七 - 路由的更多相关文章
- xmlplus 组件设计系列之零 - xmlplus 简介
xmlplus 是什么 xmlplus 是博主写的一个 JavaScript 框架,用于快速开发前后端项目. xmlplus 基于组件设计,组件是基本的构造块.评价组件设计好坏的一个重要标准是封装度. ...
- xmlplus 组件设计系列之三 - 文本框
文本框是页面中最常用的输入组件,它的默认使用方式如下: <input type='text'/> 当然,这里的 `type='text' 可以略去不写.大部分情况下,使用默认的文本框作为输 ...
- xmlplus 组件设计系列之二 - 按钮
除了图标以外,按钮也许是最简单的组件了,现在来看看如何定义按钮组件. 使用原生按钮组件 在 xmlplus 中,HTML 元素也以组件的方式存在.所以,你可以直接通过使用 button 标签或者 in ...
- xmlplus 组件设计系列之一 - 图标
网页上使用的图标分可为三种:文件图标.字体图标和 SVG 图标.对于文件图标,下面仅以 PNG 格式来说明. PNG 图标 对于 PNG 图标的引用,有两种方式.一种是直接由 HTML 元素 img ...
- xmlplus 组件设计系列之五 - 选项卡
这一章将设计一个选项卡组件,选项卡组件在手持设备上用的比较多,下面是一个示意图: 选项卡组件的分解 在具体实现之前,想像一下目标组件是如何使用的,对于设计会有莫大的帮助.通过观察,可以将选项卡组件分为 ...
- xmlplus 组件设计系列之六 - 下拉刷新
"下拉刷新"由著名设计师 Loren Brichter 设计,并应用于 Twitter 第三方应用 Tweetie 中.2010年4月,Twitter 收购 Tweetie 开发商 ...
- xmlplus 组件设计系列之八 - 分隔框(DividedBox)
分隔框(DividedBox)是一种布局类组件,可以分为两类,其中一类叫水平分隔框(HDividedBox),另一类叫垂直分隔框(VDividedBox).水平分隔框会将其子级分为两列,而垂直分隔框则 ...
- xmlplus 组件设计系列之九 - 树(Tree)
树形组件是一种具有层级结构的组件,广泛应用于各种场景.本章会实现一个简单的树形组件,尽管功能有限,但你可以通过扩展它来实现自己所需要的树形组件. 数据源 树形组件的数据源可以是 JSON 格式的数据对 ...
- xmlplus 组件设计系列之十 - 网格(DataGrid)
这一章我们要实现是一个网格组件,该组件除了最基本的数据展示功能外,还提供排序以及数据过滤功能. 数据源 为了测试我们即将编写好网格组件,我们采用如下格式的数据源.此数据源包含两部分的内容,分别是表头数 ...
随机推荐
- OpenStack/devstack with Neutron on Ubuntu 14 (1)
安装前,推荐安装一个全新的Ubuntu Server14.04,如果使用之前的ubuntu, 中间可能遇到各种的python包依赖,以及软件版本不对应的问题 环境准备,新建stack用户,给予sudo ...
- Windows下GIT安装与使用(上传远程端)
Windows下GIT安装与使用(上传远程服务器) 1. 登陆http://msysgit.github.io/并下载Git 2. 打开下载的exe文件,一路默认(路径可以去修改).有可能电脑需要 ...
- Java基础——深入理解Java中的final关键字(转载)
Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...
- iOS开发之MapKit
1.概述 MapKit框架使用前提: 导入框架: 导入主头文件: #import <MapKit/MapKit.h> MapKit框架使用须知: MapKit框架中所有数据类型的前缀都是M ...
- 实验楼-1-Hello world!
初识实验楼,决定在上面好好的练练手. Course 1 : print "Hello world" 在虚拟机桌面,打开终端Xfce,通过运行linux指令,新建c文件,进行编辑,编 ...
- Unity 3D Framework Designing(8)——使用ServiceLocator实现对象的注入
对象的 『注入』 是企业级软件开发经常听到的术语.如果你是一个 Java 程序员,一定对注入有着深刻的映像.不管是SSH框架还是SSM框架,Spring 全家桶永远是绕不过去的弯.通过依赖注入,可以有 ...
- iOS 中的单例设计模式
单例设计模式:在它的核心结构中只包含一个被称为单例类的特殊类.例如文件管理中的NSUserDefault,应用程序中的UIApplication,整个应用程序就这一个单例类,负责应用程序的一些操作,单 ...
- TextView的几个属性
1. android:autoLink 自动识别文本中包含的链接,如网址.邮箱.电话.地图等:属性值有如下几种: web------------ ------只识别网址 email---------- ...
- Java中执行shell笔记
在java中执行shell有好几种方式:第一种(exec)方式一 public static synchronized void runshell2() { File superuser = n ...
- 关于Form表单一些基础知识
1.两个重要属性: action:表单需要提交的服务器地址 method:表单提交数据使用的方法,get/post >>>get和post的区别 ①get传参使用URL传递,所有参数 ...