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 相关文章推荐
XHTML下,JS浮动代码失效的问题
Nov 12 Javascript
Javascript字符串对象的常用方法简明版
Jun 26 Javascript
IE6/IE7中JavaScript json提示缺少标识符、字符串或数字问题处理
Dec 16 Javascript
jQuery检查事件是否触发的方法
Jun 26 Javascript
JavaScript jquery及AJAX小结
Jan 24 Javascript
jQuery EasyUI tree增加搜索功能的实现方法
Apr 27 jQuery
JavaScript 用fetch 实现异步下载文件功能
Jul 21 Javascript
基于js 本地存储(详解)
Aug 16 Javascript
详解webpack提取第三方库的正确姿势
Dec 22 Javascript
AngularJS双向数据绑定原理之$watch、$apply和$digest的应用
Jan 30 Javascript
AngularJS实现的base64编码与解码功能示例
May 17 Javascript
Vue data的数据响应式到底是如何实现的
Feb 11 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一些服务器端特性的配置加强php的安全
2006/10/09 PHP
关于ob_get_contents(),ob_end_clean(),ob_start(),的具体用法详解
2013/06/24 PHP
PHP面向对象之事务脚本模式(详解)
2017/06/07 PHP
网页开发中的容易忽略的问题 javascript HTML中的table
2009/04/15 Javascript
基于jQuery的星级评分插件
2011/08/12 Javascript
jquery预览图片实现鼠标放上去显示实际大小
2014/01/16 Javascript
jquery中的常用事件bind、hover、toggle等示例介绍
2014/07/21 Javascript
在浏览器中打开或关闭JavaScript的方法
2015/06/03 Javascript
使用HTML+CSS+JS制作简单的网页菜单界面
2015/07/27 Javascript
打字效果动画的4种实现方法(超简单)
2017/10/18 Javascript
jQuery进阶实践之利用最优雅的方式如何写ajax请求
2017/12/20 jQuery
vue脚手架及vue-router基本使用
2018/04/09 Javascript
Mint-UI时间组件起始时间问题及时间插件使用
2018/08/20 Javascript
nodejs中request库使用HTTPS代理的方法
2019/04/30 NodeJs
Vue配置marked链接添加target=&quot;_blank&quot;的方法
2019/07/19 Javascript
Vue中遍历数组的新方法实例详解
2019/07/21 Javascript
解决Vue的文本编辑器 vue-quill-editor 小图标样式排布错乱问题
2020/08/03 Javascript
[01:39](回顾)各路豪强针锋相对,几经鏖战四强产生
2014/07/01 DOTA
一条命令解决mac版本python IDLE不能输入中文问题
2018/05/15 Python
python解析json串与正则匹配对比方法
2018/12/20 Python
Python列表切片常用操作实例解析
2019/12/16 Python
python drf各类组件的用法和作用
2021/01/12 Python
python生成word合同的实例方法
2021/01/12 Python
anaconda升级sklearn版本的实现方法
2021/02/22 Python
波兰购物网站:MALL.PL
2019/05/01 全球购物
List、Map、Set三个接口,存取元素时,各有什么特点?
2015/09/27 面试题
让生命充满爱演讲稿
2014/05/10 职场文书
音乐兴趣小组活动总结
2014/07/07 职场文书
2014年班组建设工作总结
2014/12/01 职场文书
大学生创业事迹材料
2014/12/30 职场文书
隐形的翅膀观后感
2015/06/10 职场文书
学生会招新宣传语
2015/07/13 职场文书
家庭教育教师培训学习体会
2016/01/14 职场文书
导游词之丽江普济寺
2019/10/22 职场文书
《杜鹃的婚约》OP主题曲「凸凹」无字幕影像公开
2022/04/08 日漫
win10音频服务未响应怎么解决?win10音频服务未响应未修复的解决方法
2022/08/14 数码科技