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 相关文章推荐
基于jQuery的表格操作插件
Apr 22 Javascript
Javascript变量函数浅析
Sep 02 Javascript
jQuery下的动画处理总结
Oct 10 Javascript
原生JS绑定滑轮滚动事件兼容常见浏览器
Jun 30 Javascript
jQuery Validate表单验证深入学习
Dec 18 Javascript
js 定位到某个锚点的方法
Nov 19 Javascript
vue+php实现的微博留言功能示例
Mar 16 Javascript
微信小程序地图实现展示线路
Jul 29 Javascript
vue实现移动端拖动排序
Aug 21 Javascript
axios封装与传参示例详解
Oct 18 Javascript
WebPack工具运行原理及入门教程
Dec 02 Javascript
80行代码写一个Webpack插件并发布到npm
May 24 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 mysql_query执行超时(Fatal error: Maximum execution time …)
2013/07/03 PHP
jQuery+Ajax+PHP“喜欢”评级功能实现代码
2015/10/08 PHP
php正则去除网页中所有的html,js,css,注释的实现方法
2016/11/03 PHP
JS案例分享之金额小写转大写
2014/05/15 Javascript
chrome下jq width()方法取值为0的解决方法
2014/05/26 Javascript
jquery使用hide方法隐藏指定id的元素
2015/03/30 Javascript
JS实现自定义简单网页软键盘效果代码
2015/11/05 Javascript
jQuery解析json数据实例分析
2015/11/24 Javascript
jQuery回到顶部的代码
2016/07/09 Javascript
详解js中Number()、parseInt()和parseFloat()的区别
2016/12/20 Javascript
Angular.js通过自定义指令directive实现滑块滑动效果
2017/10/13 Javascript
5 种JavaScript编码规范
2018/01/30 Javascript
jquery.onoff实现简单的开关按钮功能(推荐)
2018/05/24 jQuery
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧滑动,右侧不动)
2019/01/23 Javascript
解决layui表格的表头不滚动的问题
2019/09/04 Javascript
vue中实现点击空白区域关闭弹窗的两种方法
2020/12/30 Vue.js
Python程序员开发中常犯的10个错误
2014/07/07 Python
python爬虫获取新浪新闻教学
2018/12/23 Python
python连接mongodb集群方法详解
2020/02/13 Python
Python单链表原理与实现方法详解
2020/02/22 Python
Python实现中英文全文搜索的示例
2020/12/04 Python
css3 box-sizing属性使用参考指南
2013/01/08 HTML / CSS
html5声频audio和视频video等新特性详细说明
2012/12/26 HTML / CSS
ellesse美国官方商店:意大利高级运动服品牌
2019/10/29 全球购物
SQL注入攻击的种类有哪些
2013/12/30 面试题
思想品德课教学反思
2014/02/10 职场文书
材料专业毕业生求职信
2014/02/26 职场文书
环保公益广告语
2014/03/13 职场文书
面试自我介绍演讲稿
2014/04/29 职场文书
驾驶员培训方案
2014/05/01 职场文书
应届大学生求职信
2014/07/20 职场文书
民政局办理协议离婚(范本)
2014/10/25 职场文书
2014年人事行政工作总结
2014/12/03 职场文书
遗失说明具结保证书
2015/02/26 职场文书
装修公司工程部经理岗位职责
2015/04/09 职场文书
阿甘正传观后感
2015/06/01 职场文书