From efdfd6691f8114b2bf0630de76fed465675969ed Mon Sep 17 00:00:00 2001 From: neverland Date: Thu, 16 Aug 2018 21:29:11 +0800 Subject: [PATCH] [new feature] add Tabbar component (#435) --- docs/src/Preview.vue | 1 + example/app.json | 1 + example/config.js | 4 ++ example/pages/tabbar/index.js | 18 ++++++ example/pages/tabbar/index.json | 8 +++ example/pages/tabbar/index.wxml | 20 +++++++ example/pages/tabbar/index.wxss | 3 + packages/tabbar-item/index.js | 36 ++++++++++++ packages/tabbar-item/index.json | 6 ++ packages/tabbar-item/index.pcss | 45 +++++++++++++++ packages/tabbar-item/index.wxml | 18 ++++++ packages/tabbar/README.md | 97 +++++++++++++++++++++++++++++++++ packages/tabbar/index.js | 68 +++++++++++++++++++++++ packages/tabbar/index.json | 3 + packages/tabbar/index.pcss | 13 +++++ packages/tabbar/index.wxml | 6 ++ 16 files changed, 347 insertions(+) create mode 100644 example/pages/tabbar/index.js create mode 100644 example/pages/tabbar/index.json create mode 100644 example/pages/tabbar/index.wxml create mode 100644 example/pages/tabbar/index.wxss create mode 100644 packages/tabbar-item/index.js create mode 100644 packages/tabbar-item/index.json create mode 100644 packages/tabbar-item/index.pcss create mode 100644 packages/tabbar-item/index.wxml create mode 100644 packages/tabbar/README.md create mode 100644 packages/tabbar/index.js create mode 100644 packages/tabbar/index.json create mode 100644 packages/tabbar/index.pcss create mode 100644 packages/tabbar/index.wxml 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 @@ + + +