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 相关文章推荐
使用onbeforeunload属性后的副作用
Mar 08 Javascript
Mootools 1.2教程 函数
Sep 15 Javascript
javascript获取当前的时间戳的方法汇总
Jul 26 Javascript
jQuery右侧选项卡焦点图片轮播特效代码分享
Sep 05 Javascript
Jquery全屏相册插件zoomvisualizer具有调节放大与缩小功能
Nov 02 Javascript
详解javascript实现瀑布流列式布局
Jan 29 Javascript
使用jQuery判断Div是否在可视区域的方法 判断div是否可见
Feb 17 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
Feb 20 Javascript
vue+webpack实现异步组件加载的方法
Feb 03 Javascript
详解微信小程序获取当前时间及日期的方法
Apr 28 Javascript
微信小程序iOS下拉白屏晃动问题解决方案
Oct 12 Javascript
基于Web Audio API实现音频可视化效果
Jun 12 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
农民C键的运用技巧
2020/03/04 星际争霸
PHP 文件上传源码分析(RFC1867)
2009/10/30 PHP
PHP chmod 函数与批量修改文件目录权限
2010/05/10 PHP
删除无限分类并同时删除它下面的所有子分类的方法
2010/08/08 PHP
Yii2实现自定义独立验证器的方法
2017/05/05 PHP
phpcms配置列表页以及获得文章发布时间
2017/07/04 PHP
在云虚拟主机部署thinkphp5项目的步骤详解
2017/12/21 PHP
php获取ajax的headers方法与内容实例
2017/12/27 PHP
用js计算页面执行时间的函数
2006/12/07 Javascript
jquery.pagination.js 无刷新分页实现步骤分享
2012/05/23 Javascript
JavaScript中九种常用排序算法
2014/09/02 Javascript
js实现异步循环实现代码
2016/02/16 Javascript
JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)
2016/05/20 Javascript
Jquery 自定义事件实现发布/订阅的简单实例
2016/06/12 Javascript
jquery html5 视频播放控制代码
2016/11/06 Javascript
关于Node.js的events.EventEmitter用法介绍
2017/04/01 Javascript
js解决软键盘遮挡输入框的问题分享
2017/12/19 Javascript
Vue2.0 实现歌手列表滚动及右侧快速入口功能
2018/08/08 Javascript
Vue2.0生命周期的理解
2018/08/20 Javascript
js实现导航跟随效果
2018/11/17 Javascript
javascript json对象小技巧之键名作为变量用法分析
2019/11/11 Javascript
[03:42]2018完美盛典-《加冕》
2018/12/16 DOTA
Python中的闭包实例详解
2014/08/29 Python
python的格式化输出(format,%)实例详解
2018/06/01 Python
Python判断有效的数独算法示例
2019/02/23 Python
python 判断txt每行内容中是否包含子串并重新写入保存的实例
2020/03/12 Python
Django如何使用redis作为缓存
2020/05/21 Python
lululemon美国官网:瑜伽服+跑步装备
2018/11/16 全球购物
小学清明节活动方案
2014/03/08 职场文书
2015年资料员工作总结
2015/04/25 职场文书
js实现模拟购物商城案例
2021/05/18 Javascript
mysql优化之query_cache_limit参数说明
2021/07/01 MySQL
使用HttpSessionListener监听器实战
2022/03/17 Java/Android
集英社今正式宣布 成立游戏公司“集英社Games”
2022/03/31 其他游戏
vue二维数组循环嵌套方式 循环数组、循环嵌套数组
2022/04/24 Vue.js
vue el-table实现递归嵌套的示例代码
2022/08/14 Vue.js