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 相关文章推荐
document.documentElement &amp;&amp; document.documentElement.scrollTop
Dec 01 Javascript
谷歌浏览器 insertCell与appendChild的区别
Feb 12 Javascript
Jquery知识点三 jquery表单对象操作
Jan 17 Javascript
js 图片随机不定向浮动的实现代码
Jul 02 Javascript
Extjs grid panel自带滚动条失效的解决方法
Sep 11 Javascript
jQuery中:only-child选择器用法实例
Jan 03 Javascript
jQuery满屏焦点图左右滚动特效代码分享
Sep 07 Javascript
微信小程序onLaunch异步,首页onLoad先执行?
Sep 20 Javascript
vue 实现cli3.0中使用proxy进行代理转发
Oct 30 Javascript
Vue 实现v-for循环的时候更改 class的样式名称
Jul 17 Javascript
原生jQuery实现只显示年份下拉框
Dec 24 jQuery
vue里使用create, mounted调用方法
Apr 26 Vue.js
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实现的生成静态HTML速度快类库
2007/03/31 PHP
php中取得文件的后缀名?
2012/02/20 PHP
php中print(),print_r(),echo()的区别详解
2014/12/01 PHP
JS 面向对象之神奇的prototype
2011/02/26 Javascript
背景图跟随鼠标移动的Mootools插件实现代码
2011/12/12 Javascript
js选择并转移导航菜单示例代码
2014/08/19 Javascript
Javascript学习指南
2014/12/01 Javascript
jquery中关于bind()方法的使用技巧分享
2017/03/30 jQuery
canvas基础绘制-绚丽倒计时的实例
2017/09/17 Javascript
在vue项目中使用sass的配置方法
2018/03/20 Javascript
Django+vue跨域问题解决的详细步骤
2019/01/20 Javascript
Nodejs核心模块之net和http的使用详解
2019/04/02 NodeJs
js 计数排序的实现示例(升级版)
2020/01/12 Javascript
javascript实现电商放大镜效果
2020/11/23 Javascript
[01:32:22]DOTA2-DPC中国联赛 正赛 Ehome vs VG BO3 第一场 2月5日
2021/03/11 DOTA
Python编程之string相关操作实例详解
2017/07/22 Python
Django如何防止定时任务并发浅析
2019/05/14 Python
tensorflow 实现打印pb模型的所有节点
2020/01/23 Python
PythonPC客户端自动化实现原理(pywinauto)
2020/05/28 Python
10行Python代码实现Web自动化管控的示例代码
2020/08/14 Python
HTML5实现移动端弹幕动画效果
2019/08/01 HTML / CSS
戴森台湾线上商城:Dyson Taiwan
2018/05/21 全球购物
Groupon荷兰官方网站:高达70%的折扣
2019/11/01 全球购物
Piercing Pagoda官网:耳环、戒指、项链、手链等
2020/09/28 全球购物
学生周末长期请假条
2014/02/15 职场文书
给校长的一封建议书
2014/03/12 职场文书
社区矫正工作方案
2014/06/04 职场文书
学校政风行风评议心得体会
2014/10/21 职场文书
大连导游词
2015/02/12 职场文书
建筑技术负责人岗位职责
2015/04/13 职场文书
复兴之路观后感
2015/06/02 职场文书
python使用pygame创建精灵Sprite
2021/04/06 Python
如何使用Python对NetCDF数据做空间相关分析
2021/04/21 Python
用python自动生成日历
2021/04/24 Python
goland 清除所有的默认设置操作
2021/04/28 Golang
vue3语法糖内的defineProps及defineEmits
2022/04/14 Vue.js