xmlplus 组件设计系列之五 - 选项卡

时间:2022-01-19 06:13:34

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

xmlplus 组件设计系列之五 - 选项卡

选项卡组成

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

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

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

<!-- 05-01 -->
<a id="tabitem">
<Icon id="icon"/>
<span id="label">首页</span>
</a>

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

结构图

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

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

图标的实现

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

// 05-01
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 之下,也就是你要像下面这样导入:

// 05-01
xmlplus("ui", function (xp, $_, t) {
$_().imports({Tabbar: {... }, TabItem: {...}}); $_("icon").imports({--这里包含了四个图标组件--});
});

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

// 05-01
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 属性。

// 05-01
TabItem: {
css: `a#tabitem { display: table-cell; overflow: hidden; width: 1%; height: 50px; text-align: center; ... }
#label { display: block; font-size: .75em; overflow: hidden; text-overflow: ellipsis; -webkit-user-select: none; }
a#primary { color: #337ab7; fill: currentColor; }`,
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(bool) {
sys.tabitem[bool ? 'addClass' : 'removeClass']("#primary");
}
return Object.defineProperty({}, "selected", { set: select});
}
}

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

选项卡的实现

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

// 05-01
Tabbar: {
css: `#tabbar { display: table; width: 100%; height: 50px; padding: 0; table-layout: fixed; -webkit-touch-callout: none; }
#tabbar { z-index: 10; background-color: #f7f7f7; backface-visibility: hidden; }`,
xml: `<nav id="tabbar"/>`,
fun: function (sys, items, opts) {
var sel = this.first();
this.on("touchend", "./*[@id]", function (e) {
sel.value().selected = false;
(sel = this).value().selected = true;
this.trigger("switch", this.toString());
});
if (sel) sel.value().selected = true;
}
}

至此,一个选项卡组件算是完成了,下面来看下具体的一个测试示例。注意,最好在 chrome 浏览器的移动模式下做测试,这样 touchend 事件才会生效。

// 05-01
Index: {
xml: `<Tabbar id="index">
<TabItem id="home" label="首页"/>
<TabItem id="setting" label="设置"/>
<TabItem id="logs" label="日志"/>
<TabItem id="about" label="关于"/>
</Tabbar>`,
fun: function (sys, items, opts) {
this.on("switch", (e, target) => console.log(target));
}
}

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

xmlplus 组件设计系列之五 - 选项卡的更多相关文章

  1. xmlplus 组件设计系列之零 - xmlplus 简介

    xmlplus 是什么 xmlplus 是博主写的一个 JavaScript 框架,用于快速开发前后端项目. xmlplus 基于组件设计,组件是基本的构造块.评价组件设计好坏的一个重要标准是封装度. ...

  2. xmlplus 组件设计系列之三 - 文本框

    文本框是页面中最常用的输入组件,它的默认使用方式如下: <input type='text'/> 当然,这里的 `type='text' 可以略去不写.大部分情况下,使用默认的文本框作为输 ...

  3. xmlplus 组件设计系列之二 - 按钮

    除了图标以外,按钮也许是最简单的组件了,现在来看看如何定义按钮组件. 使用原生按钮组件 在 xmlplus 中,HTML 元素也以组件的方式存在.所以,你可以直接通过使用 button 标签或者 in ...

  4. xmlplus 组件设计系列之一 - 图标

    网页上使用的图标分可为三种:文件图标.字体图标和 SVG 图标.对于文件图标,下面仅以 PNG 格式来说明. PNG 图标 对于 PNG 图标的引用,有两种方式.一种是直接由 HTML 元素 img ...

  5. xmlplus 组件设计系列之六 - 下拉刷新

    "下拉刷新"由著名设计师 Loren Brichter 设计,并应用于 Twitter 第三方应用 Tweetie 中.2010年4月,Twitter 收购 Tweetie 开发商 ...

  6. xmlplus 组件设计系列之八 - 分隔框(DividedBox)

    分隔框(DividedBox)是一种布局类组件,可以分为两类,其中一类叫水平分隔框(HDividedBox),另一类叫垂直分隔框(VDividedBox).水平分隔框会将其子级分为两列,而垂直分隔框则 ...

  7. xmlplus 组件设计系列之九 - 树(Tree)

    树形组件是一种具有层级结构的组件,广泛应用于各种场景.本章会实现一个简单的树形组件,尽管功能有限,但你可以通过扩展它来实现自己所需要的树形组件. 数据源 树形组件的数据源可以是 JSON 格式的数据对 ...

  8. xmlplus 组件设计系列之十 - 网格(DataGrid)

    这一章我们要实现是一个网格组件,该组件除了最基本的数据展示功能外,还提供排序以及数据过滤功能. 数据源 为了测试我们即将编写好网格组件,我们采用如下格式的数据源.此数据源包含两部分的内容,分别是表头数 ...

  9. xmlplus 组件设计系列之四 - 列表

    列表组件是极其常用的一类组件,是许多视图组件系统的必须包含的.列表可以做的很简单,只显示简洁的内容.列表也可以做的很复杂,用于展示非常丰富的内容. 组成元素 列表离不开列表项以及包含列表项的容器.下面 ...

随机推荐

  1. vim的撤销和恢复操作以及匹配当前单词操作

    今天顺便看了一下vim的一点命令,记录一下 1.撤销上一次操作和恢复上一次操作: u → undo <C-r> → redo 2.搜索上一个单词和下一个单词 * 和 #: 匹配光标当前所在 ...

  2. 使用label在winfrom中添加分割线

    1.水平分隔线:GroupBox2. 水平,垂直分隔: Lable (AutoSize = false, BorderStyle= Fixed3D , 还要调整Size的大小 水平调整Height = ...

  3. PLSQL&lowbar;长脚本如何判断需耗时多久v&period;sql &sol; v&period;sqltext &sol; v&period;sqlarea &sol; v&period;sql&lowbar;plan及nohup(案例)

    2014-08-27 Created By BaoXinjian

  4. java I&sol;O Stream 代码学习总结

    一. InputStream 类学习介绍 mark方法 public void mark(int readlimit) 在此输入流中标记当前的位置.对 reset 方法的后续调用会在最后标记的位置重新 ...

  5. Windows环境下tomcat配置日志输出

    在Linux系统中,可以通过tail  -f  catalina.out 来跟踪Tomcat 和相关应用运行的情况. 在windows下,catalina日志与Linux记录的内容有很大区别,大多信息 ...

  6. IOS 文件管理 2

    IOS开发-文件管理(二) 五.Plist文件 String方式添加               NSString *path = [NSHomeDirectory( )  stringByAppen ...

  7. Qt编程之QImage类小结

    最近用Qt做图像处理,以下references是需要用到的 references: http://blog.csdn.net/lyc_daniel/article/details/9193881 ht ...

  8. IOS开发创建开发证书及发布App应用&lpar;八&rpar;——使用Application Loader工具上传应用

    8.使用Application Loader工具上传应用 继续第七步在iTunes所创建的应用,打开应用,如下图 点击详情按钮进去之后,单击右上角Ready to Upload Binary按钮,如下 ...

  9. MyBatis动态SQL(认真看看, 以后写SQL就爽多了)

    目录 0 一起来学习 mybatis 1 数据准备 2 if 标签 2.1 在 WHERE 条件中使用 if 标签 2.1.1 查询条件 2.1.2 动态 SQL 2.1.3 测试 2.2 在 UPD ...

  10. Windows Mysql binlog 数据恢复

    show variables like 'log_bin%'; 可以看到Mysql binlog为关闭状态,那我们去更改为开启状态