xmlplus组件设计系列之路由(ViewStack)(7)


Posted in Javascript onMay 02, 2017

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

视图栈初步

该组件在《文档》部分的最后一个章节《延迟实例化》已经出现过了。这里将对一些细节部分进行解读。下面再次给出该组件的源码。

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 某一儿子组件对象的名称,它用于指出哪一个子级组件会被最先呈现。请看下面的示例。

Example1: {
 xml: `<ViewStack index='bar'>
    <button id='foo'>foo</button>
    <button id='bar'>bar</button>
   </ViewStack>`
}

该示例中,ViewStack 包含一值为 bar 的属性 index,表明组件在实例化时,组件对象 bar 会最先呈现。而默认情况下,该组件的第一个子级组件会作为初始显示对象。再从动态接口看,该组件的函数项导出了一个名为 selected 的只读属性,该属性用于指示当前显示的子级组件对象。

通过事件切换目标组件对象

对于子级组件对象之间切换,该组件的函数项并未导出相关的接口,而是通过接收 switch 事件来完成切换。请看下面的示例。

Example2: {
 xml: "<ViewStack id='viewstack'>\
    <button id='foo'>foo</button>\
    <button id='bar'>bar</button>\
   </ViewStack>"
 fun: function (sys, items, opts) {
  sys.viewstack.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 支持动态添加与移除子级的组件对象,请看下面的一个示例。

Example3: {
 xml: "<ViewStack id='viewstack'>\
    <button id='foo'>foo</button>\
   </ViewStack>"
 fun: function (sys, items, opts) {
  var xml = "<button id='bar'>bar</button>";
  sys.viewstack.append(xml).trigger("switch", "bar");
 }
}

该示例中,函数项中动态添加了一个子级组件,并且通过派发事件 switch 将当前显示的视图切换为刚新添加的视图。

优化配置

组件 ViewStack 一般配合组件的延迟实例化功能使用。对于一些比较复杂的组件,这样有助于加快显示应用的初始页面。下面做简单示范。

Example4: {
 xml: `<ViewStack>
    <button id='foo'>foo</button>
    <button id='bar'>bar</button>
    <button id='alice'>alice</button>
   </ViewStack>`
 map: { defer: "bar alice" }
}

此示例中,ViewStack 子级包含三个子组件,其中组件对象 bar 和 alice 被设置为需要延迟实例化,只有当这两组件对象的 show 函数得到调用时,它们才真正开始实例化。

与 HTML5 History API 的配合使用

这里我们看看如何让组件 ViewStack 与 HTML5 History API 的配合使用。下面是一个简单的例子。

Example5: {
 xml: `<ViewStack id='example'>
    <button id='foo'>foo</button>
    <button id='bar'>bar</button>
    <button id='alice'>alice</button>
   </ViewStack>`,
 fun: function (sys, items, opts) {
  sys.example.on("show", "button", function (e, prev) {
   window.history.pushState({name: this + ""}, null, "/" + this);
  });
  window.addEventListener("popstate", function(e) {
   sys.example.trigger("switch", e.state.name);
  });
 }
}

该示例的关键点在于,当视图栈组件对象的子级页面发生变更时,使用函数 pushState 记录下来;另外需要侦听浏览器的 popstate 事件,当用户点击「前进」、「后退」按钮时,完成相应页面的切换。这种技术非常适合在单页应用中完成无刷新跳转,可以给用户带来非常好的体验。

本系列文章基于 xmlplus 框架。如果你对 xmlplus 没有多少了解,可以访问 www.xmlplus.cn。这里有详尽的入门文档可供参考。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript使用window.open提示“已经计划系统关机”的原因
Aug 15 Javascript
node.js中的querystring.unescape方法使用说明
Dec 10 Javascript
JS仿Base.js实现的继承示例
Apr 07 Javascript
Vue单文件组件基础模板小结
Aug 10 Javascript
JavaScript实现单击网页任意位置打开新窗口与关闭窗口的方法
Sep 21 Javascript
探讨Vue.js的组件和模板
Oct 27 Javascript
Laravel整合Bootstrap 4的完整方案(推荐)
Jan 25 Javascript
Vue实现按钮旋转和移动位置的实例代码
Aug 09 Javascript
webuploader分片上传的实现代码(前后端分离)
Sep 10 Javascript
为什么Vue3.0使用Proxy实现数据监听(defineProperty表示不背这个锅)
Oct 14 Javascript
javascript设计模式 ? 单例模式原理与应用实例分析
Apr 09 Javascript
JS操作JSON常用方法(10w阅读)
Dec 06 Javascript
JavaScript比较两个数组的内容是否相同(推荐)
May 02 #Javascript
xmlplus组件设计系列之分隔框(DividedBox)(8)
May 02 #Javascript
xmlplus组件设计系列之树(Tree)(9)
May 02 #Javascript
详解Vue2.X的路由管理记录之 钩子函数(切割流水线)
May 02 #Javascript
令按钮悬浮在(手机)页面底部的实现方法
May 02 #Javascript
Vue2.0表单校验组件vee-validate的使用详解
May 02 #Javascript
ES6学习教程之对象的扩展详解
May 02 #Javascript
You might like
php批量删除数据
2007/01/18 PHP
Apache环境下PHP利用HTTP缓存协议原理解析及应用分析
2010/02/16 PHP
5种PHP创建数组的实例代码分享
2014/01/17 PHP
PHP中使用strpos函数实现屏蔽敏感关键字功能
2014/08/21 PHP
PHP超牛逼无限极分类生成树方法
2015/05/11 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
线路分流自动跳转代码;希望对大家有用!
2006/12/02 Javascript
Flash对联广告的关闭按钮讨论
2007/01/30 Javascript
js获取dom的高度和宽度(可见区域及部分等等)
2013/06/13 Javascript
js捕获鼠标滚轮事件代码
2013/12/16 Javascript
jquery简单实现鼠标经过导航条改变背景图
2013/12/17 Javascript
JavaScript indexOf方法入门实例(计算指定字符在字符串中首次出现的位置)
2014/10/17 Javascript
通过点击jqgrid表格弹出需要的表格数据
2015/12/02 Javascript
JavaScript+html5 canvas制作的百花齐放效果完整实例
2016/01/26 Javascript
基于jquery实现智能提示控件intellSeach.js
2016/03/17 Javascript
浅谈JS继承_寄生式继承 &amp; 寄生组合式继承
2016/08/16 Javascript
JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码
2017/08/18 Javascript
浅谈JavaScript_DOM学习篇_图片切换小案例
2019/03/19 Javascript
vue中使用vue-pdf的方法详解
2020/09/05 Javascript
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
[01:28:31]《加油DOTA》真人秀 第五期
2014/09/01 DOTA
python实现文本去重且不打乱原本顺序
2016/01/26 Python
Python中dict和set的用法讲解
2019/03/28 Python
Python3列表内置方法大全及示例代码小结
2019/05/10 Python
Python pandas 列转行操作详解(类似hive中explode方法)
2020/05/18 Python
基于Python第三方插件实现西游记章节标注汉语拼音的方法
2020/05/22 Python
使用python求斐波那契数列中第n个数的值示例代码
2020/07/26 Python
python中time、datetime模块的使用
2020/12/14 Python
Exoticca英国:以最优惠的价格提供豪华异国情调旅行
2018/10/18 全球购物
C语言中一个结构不能包含指向自己的指针吗
2012/05/25 面试题
AJAX的优缺点都有什么
2015/08/18 面试题
高中班级口号
2014/06/09 职场文书
初中团委工作总结
2015/08/13 职场文书
pytorch MSELoss计算平均的实现方法
2021/05/12 Python
Python人工智能之混合高斯模型运动目标检测详解分析
2021/11/07 Python
【DOTA2】总决赛血虐~ XTREME GAMING vs MAGMA - OGA DOTA PIT 2022 CN
2022/04/02 DOTA