diff --git a/docs/src/Preview.vue b/docs/src/Preview.vue
index e3f8c635..303fd2f2 100644
--- a/docs/src/Preview.vue
+++ b/docs/src/Preview.vue
@@ -33,6 +33,7 @@ const MAP = {
steps: 'steps-201808092138.png',
switch: 'switch-201808092138.png',
tag: 'tag-201808092138.png',
+ tabbar: 'tabbar-201808160922.png',
'tree-select': 'tree-select-201808092138.png'
};
diff --git a/example/app.json b/example/app.json
index 3ad7b9c2..941074de 100644
--- a/example/app.json
+++ b/example/app.json
@@ -20,6 +20,7 @@
"pages/switch/index",
"pages/search/index",
"pages/tag/index",
+ "pages/tabbar/index",
"pages/tree-select/index"
],
"window": {
diff --git a/example/config.js b/example/config.js
index 12b21fad..2622236e 100644
--- a/example/config.js
+++ b/example/config.js
@@ -49,6 +49,10 @@ export default [
{
path: '/tag',
title: 'Tag 标记'
+ },
+ {
+ path: '/tabbar',
+ title: 'Tabbar 标签栏'
}
]
},
diff --git a/example/pages/tabbar/index.js b/example/pages/tabbar/index.js
new file mode 100644
index 00000000..127878b1
--- /dev/null
+++ b/example/pages/tabbar/index.js
@@ -0,0 +1,18 @@
+import Page from '../../common/page';
+
+Page({
+ data: {
+ active: 0,
+ active2: 0,
+ icon: {
+ normal:
+ 'https://img.yzcdn.cn/public_files/2017/10/13/c547715be149dd3faa817e4a948b40c4.png',
+ active:
+ 'https://img.yzcdn.cn/public_files/2017/10/13/793c77793db8641c4c325b7f25bf130d.png'
+ }
+ },
+
+ onChange(event) {
+ console.log(event.detail);
+ }
+});
diff --git a/example/pages/tabbar/index.json b/example/pages/tabbar/index.json
new file mode 100644
index 00000000..2bde3863
--- /dev/null
+++ b/example/pages/tabbar/index.json
@@ -0,0 +1,8 @@
+{
+ "navigationBarTitleText": "Tabbar 标签页",
+ "usingComponents": {
+ "demo-block": "../../components/demo-block/index",
+ "van-tabbar": "../../dist/tabbar/index",
+ "van-tabbar-item": "../../dist/tabbar-item/index"
+ }
+}
diff --git a/example/pages/tabbar/index.wxml b/example/pages/tabbar/index.wxml
new file mode 100644
index 00000000..ba7881f8
--- /dev/null
+++ b/example/pages/tabbar/index.wxml
@@ -0,0 +1,20 @@
+
+
+ 标签
+ 标签
+ 标签
+ 标签
+
+
+
+
+
+
+ 自定义
+
+
+
+ 标签
+ 标签
+
+
diff --git a/example/pages/tabbar/index.wxss b/example/pages/tabbar/index.wxss
new file mode 100644
index 00000000..98ea1074
--- /dev/null
+++ b/example/pages/tabbar/index.wxss
@@ -0,0 +1,3 @@
+.tabbar {
+ position: relative !important;
+}
diff --git a/packages/tabbar-item/index.js b/packages/tabbar-item/index.js
new file mode 100644
index 00000000..da38910c
--- /dev/null
+++ b/packages/tabbar-item/index.js
@@ -0,0 +1,36 @@
+const TABBAR_PATH = '../tabbar/index';
+
+Component({
+ name: 'tabbar-item',
+
+ properties: {
+ info: null,
+ icon: String,
+ dot: Boolean
+ },
+
+ options: {
+ multipleSlots: true
+ },
+
+ relations: {
+ [TABBAR_PATH]: {
+ type: 'ancestor'
+ }
+ },
+
+ data: {
+ active: false,
+ count: 0
+ },
+
+ methods: {
+ onClick() {
+ const parent = this.getRelationNodes(TABBAR_PATH)[0];
+ if (parent) {
+ parent.onChange(this);
+ }
+ this.triggerEvent('click');
+ }
+ }
+});
diff --git a/packages/tabbar-item/index.json b/packages/tabbar-item/index.json
new file mode 100644
index 00000000..0a336c08
--- /dev/null
+++ b/packages/tabbar-item/index.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "van-icon": "../icon/index"
+ }
+}
diff --git a/packages/tabbar-item/index.pcss b/packages/tabbar-item/index.pcss
new file mode 100644
index 00000000..42df0536
--- /dev/null
+++ b/packages/tabbar-item/index.pcss
@@ -0,0 +1,45 @@
+@import '../common/style/var.pcss';
+
+.van-tabbar-item {
+ float: left;
+ color: #666;
+ height: 100%;
+ display: flex;
+ line-height: 1;
+ font-size: 12px;
+ align-items: center;
+ flex-direction: column;
+ justify-content: center;
+
+ &__icon {
+ font-size: 18px;
+ margin-bottom: 5px;
+ position: relative;
+
+ .van-icon {
+ display: block;
+ }
+
+ &--dot {
+ &::after {
+ top: 0;
+ right: -8px;
+ width: 8px;
+ height: 8px;
+ content: ' ';
+ position: absolute;
+ border-radius: 100%;
+ background-color: $red;
+ }
+ }
+
+ image {
+ width: 50px;
+ height: 18px;
+ }
+ }
+
+ &--active {
+ color: $blue;
+ }
+}
diff --git a/packages/tabbar-item/index.wxml b/packages/tabbar-item/index.wxml
new file mode 100644
index 00000000..d888e740
--- /dev/null
+++ b/packages/tabbar-item/index.wxml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/tabbar/README.md b/packages/tabbar/README.md
new file mode 100644
index 00000000..56bcaef1
--- /dev/null
+++ b/packages/tabbar/README.md
@@ -0,0 +1,97 @@
+## Tabbar 标签栏
+
+### 使用指南
+在 index.json 中引入组件
+```json
+"usingComponents": {
+ "van-tabbar": "/packages/tabbar/index",
+ "van-tabbar-item": "/packages/tabbar-item/index"
+}
+```
+
+### 代码演示
+
+#### 基础用法
+
+
+```html
+
+ 标签
+ 标签
+ 标签
+ 标签
+
+```
+
+```javascript
+Page({
+ data: {
+ active: 0
+ },
+ // event.detail 的值为当前选中项的索引
+ onChange(event) {
+ console.log(event.detail);
+ }
+});
+```
+
+
+#### 自定义图标
+
+可以通过 slot 自定义图标,其中 icon slot 代表未选中状态下的图标,icon-active slot 代表选中状态下的图标
+
+```html
+
+
+ 自定义
+
+
+
+ 标签
+ 标签
+
+```
+
+```javascript
+Page({
+ data() {
+ active: 0,
+ icon: {
+ normal: '//img.yzcdn.cn/icon-normal.png',
+ active: '//img.yzcdn.cn/icon-active.png'
+ }
+ },
+ onChange(event) {
+ console.log(event.detail);
+ }
+});
+```
+
+### Tabbar API
+
+| 参数 | 说明 | 类型 | 默认值 |
+|-----------|-----------|-----------|-------------|
+| active | 当前选中标签的索引 | `Number` | - |
+| fixed | 是否固定在底部 | `Boolean` | `true` |
+| z-index | 元素 z-index | `Number` | `1` |
+
+### Tabbar Event
+
+| 事件名 | 说明 | 参数 |
+|-----------|-----------|-----------|
+| bind:change | 切换标签时触发 | event.detail: 当前选中标签的索引 |
+
+### TabbarItem API
+
+| 参数 | 说明 | 类型 | 默认值 |
+|-----------|-----------|-----------|-----------|
+| icon | 图标名称 (可选值见 Icon 组件) | `String` | - |
+| dot | 是否显示小红点 | `Boolean` | - |
+| info | 图标右上角提示信息 | `String | Number` | - |
+
+### TabbarItem Slot
+
+| 名称 | 说明 |
+|-----------|-----------|
+| icon | 未选中时的图标 |
+| icon-active | 选中时的图标 |
diff --git a/packages/tabbar/index.js b/packages/tabbar/index.js
new file mode 100644
index 00000000..c22d01be
--- /dev/null
+++ b/packages/tabbar/index.js
@@ -0,0 +1,68 @@
+const ITEM_PATH = '../tabbar-item/index';
+
+Component({
+ externalClasses: ['custom-class'],
+
+ properties: {
+ active: {
+ type: Number,
+ observer(active) {
+ this.setData({ currentActive: active });
+ this.setActiveItem();
+ }
+ },
+ fixed: {
+ type: Boolean,
+ value: true
+ },
+ zIndex: {
+ type: Number,
+ value: 1
+ }
+ },
+
+ data: {
+ items: [],
+ currentActive: -1
+ },
+
+ attached() {
+ this.setData({ currentActive: this.data.active });
+ },
+
+ relations: {
+ [ITEM_PATH]: {
+ type: 'descendant',
+
+ linked(target) {
+ this.data.items.push(target);
+ this.setActiveItem();
+ },
+
+ unlinked(target) {
+ this.data.items = this.data.items.filter(item => item !== target);
+ this.setActiveItem();
+ }
+ }
+ },
+
+ methods: {
+ setActiveItem() {
+ this.data.items.forEach((item, index) => {
+ item.setData({
+ active: index === this.data.currentActive,
+ count: this.data.items.length
+ });
+ });
+ },
+
+ onChange(child) {
+ const active = this.data.items.indexOf(child);
+ if (active !== this.data.currentActive && active !== -1) {
+ this.triggerEvent('change', active);
+ this.setData({ currentActive: active });
+ this.setActiveItem();
+ }
+ }
+ }
+});
diff --git a/packages/tabbar/index.json b/packages/tabbar/index.json
new file mode 100644
index 00000000..467ce294
--- /dev/null
+++ b/packages/tabbar/index.json
@@ -0,0 +1,3 @@
+{
+ "component": true
+}
diff --git a/packages/tabbar/index.pcss b/packages/tabbar/index.pcss
new file mode 100644
index 00000000..5c82251b
--- /dev/null
+++ b/packages/tabbar/index.pcss
@@ -0,0 +1,13 @@
+@import '../common/style/var.pcss';
+
+.van-tabbar {
+ width: 100%;
+ height: 50px;
+ background-color: #fff;
+
+ &--fixed {
+ left: 0;
+ bottom: 0;
+ position: fixed;
+ }
+}
diff --git a/packages/tabbar/index.wxml b/packages/tabbar/index.wxml
new file mode 100644
index 00000000..18a1ed96
--- /dev/null
+++ b/packages/tabbar/index.wxml
@@ -0,0 +1,6 @@
+
+
+