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 function调用时的参数检测常用办法
Feb 26 Javascript
基于jQuery的简单九宫格实现代码
Aug 09 Javascript
用js实现in_array的方法
Nov 05 Javascript
jquery查找父元素、子元素(个人经验总结)
Apr 09 Javascript
JS实现图片产生波纹一样flash效果的方法
Feb 27 Javascript
JS函数定义方式的区别介绍
Mar 22 Javascript
jQuery设置Cookie及删除Cookie实例分析
Apr 15 Javascript
vue-cli项目如何使用vue-resource获取本地的json数据(模拟服务端返回数据)
Aug 04 Javascript
JavaScript对象字面量和构造函数原理与用法详解
Apr 18 Javascript
JavaScript实现简单验证码
Aug 24 Javascript
react实现复选框全选和反选组件效果
Aug 25 Javascript
js实现碰撞检测
Jan 29 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中simplexml_load_string函数使用说明
2011/01/01 PHP
色色整理的PHP面试题集锦
2012/03/08 PHP
10条php编程小技巧
2015/07/07 PHP
浅谈PHP拦截器之__set()与__get()的理解与使用方法
2016/10/18 PHP
JQuery 网站换肤功能实现代码
2009/11/02 Javascript
js通过googleAIP翻译PHP系统的语言配置的实现代码
2011/10/17 Javascript
Javascript 按位左移运算符使用介绍(
2014/02/04 Javascript
可恶的ie8提示缺少id未定义
2014/03/20 Javascript
jQuery实现底部浮动窗口效果
2016/09/07 Javascript
Javascript+CSS3实现进度条效果
2016/10/28 Javascript
Vue组件中slot的用法
2018/01/30 Javascript
详解vue2.0+vue-video-player实现hls播放全过程
2018/03/02 Javascript
vue项目中实现图片预览的公用组件功能
2018/10/26 Javascript
jQuery ajax仿Google自动提示SearchSuggess功能示例
2019/03/28 jQuery
如何给element添加一个抽屉组件的方法步骤
2019/07/14 Javascript
jQuery实现的分页插件完整示例
2020/05/26 jQuery
[03:09]显微镜下的DOTA2第一期——带你走进华丽的DOTA2世界
2014/06/20 DOTA
[02:17]2016完美“圣”典风云人物:Sccc专访
2016/12/03 DOTA
python模拟登录百度代码分享(获取百度贴吧等级)
2013/12/27 Python
浅谈numpy中linspace的用法 (等差数列创建函数)
2017/06/07 Python
python中break、continue 、exit() 、pass终止循环的区别详解
2019/07/08 Python
解决Django后台ManyToManyField显示成Object的问题
2019/08/09 Python
python matplotlib:plt.scatter() 大小和颜色参数详解
2020/04/14 Python
Python打印特殊符号及对应编码解析
2020/05/07 Python
Python2.x与3​​.x版本有哪些区别
2020/07/09 Python
python实现数字炸弹游戏程序
2020/07/17 Python
python中使用.py配置文件的方法详解
2020/11/23 Python
美国知名户外用品畅销中心:Sierra Trading Post
2016/07/19 全球购物
澳大利亚在线批发商:Simply Wholesale
2021/02/24 全球购物
技校教师求职简历的自我评价
2013/10/20 职场文书
优秀毕业生推荐信
2013/11/02 职场文书
服务员岗位职责
2014/01/29 职场文书
企业爱岗敬业演讲稿
2014/09/04 职场文书
具结保证书范本
2015/05/11 职场文书
维护民族团结心得体会2016
2016/01/15 职场文书
vue使用wavesurfer.js解决音频可视化播放问题
2022/04/04 Vue.js