xmlplus组件设计系列之选项卡(Tabbar)(5)


Posted in Javascript onMay 03, 2017

这一章将设计一个选项卡组件,选项卡组件在手持设备上用的比较多,下面是一个示意图:

xmlplus组件设计系列之选项卡(Tabbar)(5)

选项卡组成

在具体实现之前,想像一下目标组件是如何使用的,对于设计会有莫大的帮助。通过观察,可以将选项卡组件分为容器部分和子项部分,正如下面的 XML 结构所展示的。

<Tabbar id="tabbar">
  <TabItem id="home" label="首页"/>
  <TabItem id="setting" label="设置"/>
  <TabItem id="logs" label="日志"/>
  <TabItem id="about" label="关于"/>
</Tabbar>

现在我们把目光切换到选项卡组件的子项部分,来看看子项部分是如何分解的。通过示意图,你可以发现子项部分可以分解为子项容器以及包含一个图标和一个文本的子级部分。

<a id="tabitem">
  <Icon id="icon"/>
  <span id="label">首页</span>
</a>

所以,现在我们的目标已经很明确了,主要设计三个组件:图标组件 Icon、选项卡组件的子项 TabItem 以及选项卡组件的容器 Tabbar。

结构图

由于该组件比较简单,所以可以将三种子组件放置在同一层级。但请注意,我们还有四个图标组件,可以创建一个子级用于容纳它们。下面给出我们的组件结构图:

Tabbar/
├── Tabbar
├── TabItem
└── Icon/
     ├── About
     ├── Home
     ├── Logs
     └── Setting

图标的实现

我们从最简单的开始,先看四个图标组件,图标组件主要通过封装 SVG 文本来实现,由于图标文本较长,所以这里仅截取每个图标文本的一段。

About: {
  xml: `<svg width="48" height="48" viewBox="0 0 1024 1024">
        <path d="M507.577907 23.272727C240.142852..."/>
     </svg>`
},
Home: {
  xml: `<svg width="48" height="48" viewBox="0 0 1024 1024">
        <path d="M949.082218 519.343245 508.704442..."/>
     </svg>`
},
Logs: {
  xml: `<svg width="48" height="48" viewBox="0 0 1024 1024">
        <path d="M576 125.344l32 0 0 64-32 0 0-64Z..."/>
     </svg>`
},
Setting: {
  xml: `<svg width="48" height="48" viewBox="0 0 1024 1024">
        <path d="M512 336.664c-96.68 0-175.336 78...."/>
     </svg>`
}

请注意,这些图标位于虚拟目录 /icon 之下,也就是你要像下面这样导入:

xmlplus("ui", function (xp, $_, t) {
  $_().imports({Tabbar: {... }, TabItem: {...}});

  $_("icon").imports({--这里包含了四个图标组件--});
});

下面来实现图标组件 Icon,这里的图标组件与上面是不同的,它会根据输入的图标类型实例化不同的图标。这样设计可以复用部分相同的代码,避免冗余。

Icon: {
  css: "#icon { width: 1.5em; height: 1.5em; display: inline-block; }",
  opt: { icon: "about" },
  xml: `<span id="icon"/>`,
  fun: function (sys, items, opts) {
    sys.icon.replace("icon/" + opts.icon).addClass("#icon");
  }
}

该组件的函数项根据输入的图标类型创建图标组件并替换已有的 span 元素对象。注意,替换完后需要重新添加样式。

子项的实现

按从内到外的原则,接下来实现选项卡组件的子项 TabItem。对于此组件,需要在组件的映射项中做一次异名的属性映射,把 id 属性值映射给内部的图标组件的 icon 属性。

TabItem: {
  css: "这里是样式项部分,为便于组件整体展示,略去...",
  map: {"attrs": { icon: "id->icon" } },
  xml: `<a id="tabitem">
       <Icon id="icon"/>
       <span id="label">首页</span>
     </a>`,
  fun: function (sys, items, opts) {
    sys.label.text(opts.label);
    function select() {
      sys.tabitem.addClass("#primary");
    }
    function unselect() {
      sys.tabitem.removeClass("#primary");
    }
    return { select: select, unselect: unselect };
  }
}

此组件提供了用于选项切换时选中与非选中状态之间切换的接口。以供选项卡容器使用。

选项卡的实现

最后来看下选项卡组件 Tabbar 的实现。该组件侦听了用户触击选项卡时的事件,在侦听器里主要做两件事:一是维持选项卡状态的切换;另一是派发一选项卡切换时的状态改变事件。

Tabbar: {
  css: "这里是样式项部分,为便于组件整体展示,略去...",
  xml: `<nav id="tabbar"/>`,
  fun: function (sys, items, opts) {
    var sel = this.first();
    this.on("touchend", "./*[@id]", function (e) {
      sel.value().unselect();
      (sel = this).value().select();
      this.trigger("switch", this.toString());
    });
    if (sel) sel.value().select();
  }
}

至此,一个选项卡组件算是完成了,下面来看下具体的一个应用:

xmlplus("example", function (xp, $_, t) {
  $_().imports({
  Index: {
    xml: `<Footer id='footer'/>`,
    fun: function (sys, items, opts) {
      this.on("switch", (e, target) => console.log(target));
    }
  },
  Footer: {
    xml: `<Tabbar id="footer">
         <TabItem id="home" label="首页"/>
         <TabItem id="setting" label="设置"/>
         <TabItem id="logs" label="日志"/>
         <TabItem id="about" label="关于"/>
       </Tabbar>`
  }
  });
});

在组件 Index 中,你可以侦听来自选项卡的切换事件来做相应的操作。比如结合后续我们介绍的视图栈组件做页面之间的切换操作。

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

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

Javascript 相关文章推荐
document对象execCommand的command参数介绍
Aug 01 Javascript
使一个函数作为另外一个函数的参数来运行的javascript代码
Aug 13 Javascript
jquery 单击li防止重复加载的实现代码
Dec 24 Javascript
JavaScript中最简洁的编码html字符串的方法
Oct 11 Javascript
jQuery插件Tmpl的简单使用方法
Apr 27 Javascript
JS实现可展开折叠层的鼠标拖曳效果
Oct 09 Javascript
js实现将选中内容分享到新浪或腾讯微博
Dec 16 Javascript
基于JSON格式数据的简单jQuery幻灯片插件(jquery-slider)
Aug 10 Javascript
jQuery动态改变多行文本框高度的方法
Sep 07 Javascript
JS实现倒计时(天数、时、分、秒)
Nov 16 Javascript
微信小程序自定义组件之可清除的input组件
Jul 17 Javascript
ES6入门教程之let、const的使用方法
Apr 13 Javascript
javascript过滤数组重复元素的实现方法
May 03 #Javascript
JS实现图片点击后出现模态框效果
May 03 #Javascript
xmlplus组件设计系列之下拉刷新(PullRefresh)(6)
May 03 #Javascript
javascript 判断一个对象为数组的方法
May 03 #Javascript
深入理解node.js之path模块
May 03 #Javascript
判断颜色是否合法的正则表达式(详解)
May 03 #Javascript
Vue input控件通过value绑定动态属性及修饰符的方法
May 03 #Javascript
You might like
提升PHP执行速度全攻略(上)
2006/10/09 PHP
Symfony2针对输入时间进行查询的方法分析
2017/06/28 PHP
PHP利用百度ai实现文本和图片审核
2019/05/08 PHP
用javascript实现给图片加链接
2007/08/15 Javascript
禁止JQuery中的load方法装载IE缓存中文件的方法
2009/09/11 Javascript
JavaScript对象创建及继承原理实例解剖
2013/02/28 Javascript
javascript变量作用域使用中常见错误总结
2013/03/26 Javascript
js获取select标签选中值的两种方式
2014/01/09 Javascript
js中top的作用深入剖析
2014/03/04 Javascript
IE浏览器IFrame对象内存不释放问题解决方法
2014/08/22 Javascript
AngularJS HTML编译器介绍
2014/12/06 Javascript
原生js和jQuery实现淡入淡出轮播效果
2015/12/25 Javascript
基于JavaScript实现瀑布流效果(循环渐近)
2016/01/27 Javascript
jquery.validate.js 多个相同name的处理方式
2017/07/10 jQuery
使用typescript开发angular模块并发布npm包
2018/04/19 Javascript
JS使用setInterval实现的简单计时器功能示例
2018/04/19 Javascript
Javascript实现异步编程的过程
2018/06/18 Javascript
js实现多张图片每隔一秒切换一张图片
2019/07/29 Javascript
JS在Array数组中按指定位置删除或添加元素对象方法示例
2019/11/19 Javascript
JavaScript实现图片伪异步上传过程解析
2020/04/10 Javascript
vue项目在webpack2实现移动端字体自适配功能
2020/06/02 Javascript
js实现3D旋转相册
2020/08/02 Javascript
基于python的Tkinter编写登陆注册界面
2017/06/30 Python
Python爬虫实战之12306抢票开源
2019/01/24 Python
Python计算不规则图形面积算法实现解析
2019/11/22 Python
如何用Python绘制3D柱形图
2020/09/16 Python
简单掌握CSS3中resize属性的用法
2016/04/01 HTML / CSS
杰夫·班克斯男士服装网上商店:Jeff Banks
2019/10/24 全球购物
当我正在为表建立索引的时候,SQL Server 会禁止对表的访问吗
2014/04/28 面试题
社区班子个人对照检查材料思想汇报
2014/10/07 职场文书
个人公司授权委托书范本
2014/10/12 职场文书
2014年纳税评估工作总结
2014/12/23 职场文书
婚育证明格式
2015/06/17 职场文书
早上好问候语大全
2015/11/10 职场文书
2016年“我们的节日·清明节”活动总结
2016/04/01 职场文书
详解Nginx的超时keeplive_timeout配置步骤
2022/05/25 Servers