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入门基础知识学习指南
Aug 14 Javascript
拥有一个属于自己的javascript表单验证插件
Mar 24 Javascript
BootStrap日期控件在模态框中选择时间下拉菜单无效的原因及解决办法(火狐下不能点击)
Aug 18 Javascript
前端构建工具之gulp的配置与搭建详解
Jun 12 Javascript
React Native 真机断点调试+跨域资源加载出错问题的解决方法
Jan 18 Javascript
vue中将html字符串转换成html后遇到的问题小结
Dec 10 Javascript
vue框架下部署上线后刷新报404问题的解决方案(推荐)
Apr 03 Javascript
Webpack4+Babel7+ES6兼容IE8的实现
Apr 10 Javascript
原生JS使用Canvas实现拖拽式绘图功能
Jun 05 Javascript
Vue 实现前端权限控制的示例代码
Jul 09 Javascript
jquery实现上传文件进度条
Mar 26 jQuery
使用compose函数优化代码提高可读性及扩展性
Jun 16 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
咖啡产品发展的三大浪潮
2021/03/04 咖啡文化
用PHP实现多服务器共享SESSION数据的方法
2007/03/16 PHP
php中3种方法统计字符串中每种字符的个数并排序
2012/08/27 PHP
PHP使用redis实现统计缓存mysql压力的方法
2015/11/14 PHP
Thinkphp 空操作、空控制器、命名空间(详解)
2017/05/05 PHP
Laravel如何创建服务器提供者实例代码
2019/04/15 PHP
理解JavaScript中的事件
2006/09/23 Javascript
不安全的常用的js写法
2009/09/15 Javascript
为指定的元素添加遮罩层的示例代码
2014/01/15 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
纯CSS3代码实现滑动开关效果
2015/08/19 Javascript
javascript正则表达式定义(语法)总结
2016/01/08 Javascript
Jquery插件仿百度搜索关键字自动匹配功能
2016/05/11 Javascript
JS 数字转换为大写金额的简单实例
2016/08/04 Javascript
vue.js获取数据库数据实例代码
2017/05/26 Javascript
React学习笔记之高阶组件应用
2018/06/02 Javascript
vue2.0的虚拟DOM渲染思路分析
2018/08/09 Javascript
layui prompt 设置允许空白提交的方法
2019/09/24 Javascript
javascript 内存模型实例详解
2020/04/18 Javascript
Vue中的nextTick作用和几个简单的使用场景
2021/01/25 Vue.js
python字符串替换的2种方法
2014/11/30 Python
Python常用的文件及文件路径、目录操作方法汇总介绍
2015/05/21 Python
Python验证码识别的方法
2015/07/10 Python
Django的信号机制详解
2017/05/05 Python
tensorflow创建变量以及根据名称查找变量
2018/03/10 Python
python isinstance函数用法详解
2020/02/13 Python
python 伯努利分布详解
2020/02/25 Python
如何使用Python自动生成报表并以邮件发送
2020/10/15 Python
业务主管岗位职责范本
2013/12/25 职场文书
运动会横幅标语
2014/06/17 职场文书
影视广告专业求职信
2014/09/02 职场文书
2014公司党员自我评价范文
2014/09/11 职场文书
忠诚奉献演讲稿
2014/09/12 职场文书
挂靠协议书
2015/01/27 职场文书
2015年个人实习工作总结
2015/05/28 职场文书
陈斌强事迹观后感
2015/06/17 职场文书