From f6e25a26db4944efe7e6c835e170f78268393d33 Mon Sep 17 00:00:00 2001 From: neverland Date: Sun, 19 Aug 2018 10:41:46 +0800 Subject: [PATCH] [new feature] add Toast component (#437) --- example/app.json | 1 + example/config.js | 4 ++ example/pages/toast/index.js | 41 +++++++++++++++ example/pages/toast/index.json | 8 +++ example/pages/toast/index.wxml | 18 +++++++ example/pages/toast/index.wxss | 0 packages/overlay/index.js | 11 ++++ packages/overlay/index.json | 3 ++ packages/overlay/index.pcss | 0 packages/overlay/index.wxml | 5 ++ packages/toast/README.md | 96 ++++++++++++++++++++++++++++++++++ packages/toast/index.js | 32 ++++++++++++ packages/toast/index.json | 8 +++ packages/toast/index.pcss | 69 ++++++++++++++++++++++++ packages/toast/index.wxml | 23 ++++++++ packages/toast/toast.js | 68 ++++++++++++++++++++++++ 16 files changed, 387 insertions(+) create mode 100644 example/pages/toast/index.js create mode 100644 example/pages/toast/index.json create mode 100644 example/pages/toast/index.wxml create mode 100644 example/pages/toast/index.wxss create mode 100644 packages/overlay/index.js create mode 100644 packages/overlay/index.json create mode 100644 packages/overlay/index.pcss create mode 100644 packages/overlay/index.wxml create mode 100644 packages/toast/README.md create mode 100644 packages/toast/index.js create mode 100644 packages/toast/index.json create mode 100644 packages/toast/index.pcss create mode 100644 packages/toast/index.wxml create mode 100644 packages/toast/toast.js diff --git a/example/app.json b/example/app.json index 941074de..48717b4c 100644 --- a/example/app.json +++ b/example/app.json @@ -20,6 +20,7 @@ "pages/switch/index", "pages/search/index", "pages/tag/index", + "pages/toast/index", "pages/tabbar/index", "pages/tree-select/index" ], diff --git a/example/config.js b/example/config.js index 2622236e..5db5f75f 100644 --- a/example/config.js +++ b/example/config.js @@ -84,6 +84,10 @@ export default [ path: '/actionsheet', title: 'Actionsheet 上拉菜单' }, + { + path: '/toast', + title: 'Toast 轻提示' + }, { path: '/notify', title: 'Notify 消息通知' diff --git a/example/pages/toast/index.js b/example/pages/toast/index.js new file mode 100644 index 00000000..2a1ffc45 --- /dev/null +++ b/example/pages/toast/index.js @@ -0,0 +1,41 @@ +import Page from '../../common/page'; +import Toast from '../../dist/toast/index'; + +Page({ + showToast() { + Toast('我是提示文案,建议不超过十五字~'); + }, + + showLoadingToast() { + Toast.loading({ mask: true, message: '加载中...' }); + }, + + showSuccessToast() { + Toast.success('成功文案'); + }, + + showFailToast() { + Toast.fail('失败提示'); + }, + + showCustomizedToast(duration) { + const text = second => `倒计时 ${second} 秒`; + const toast = Toast.loading({ + duration: 0, + forbidClick: true, + loadingType: 'spinner', + message: text(3) + }); + + let second = 3; + const timer = setInterval(() => { + second--; + if (second) { + toast.setData({ message: text(second) }); + } else { + clearInterval(timer); + Toast.clear(); + } + }, 1000); + } +}); diff --git a/example/pages/toast/index.json b/example/pages/toast/index.json new file mode 100644 index 00000000..bcbe4b59 --- /dev/null +++ b/example/pages/toast/index.json @@ -0,0 +1,8 @@ +{ + "navigationBarTitleText": "Toast 轻提示", + "usingComponents": { + "demo-block": "../../components/demo-block/index", + "van-toast": "../../dist/toast/index", + "van-button": "../../dist/button/index" + } +} diff --git a/example/pages/toast/index.wxml b/example/pages/toast/index.wxml new file mode 100644 index 00000000..a776096d --- /dev/null +++ b/example/pages/toast/index.wxml @@ -0,0 +1,18 @@ + + 文字提示 + + + + 加载提示 + + + + 成功提示 + 失败提示 + + + + 高级用法 + + + diff --git a/example/pages/toast/index.wxss b/example/pages/toast/index.wxss new file mode 100644 index 00000000..e69de29b diff --git a/packages/overlay/index.js b/packages/overlay/index.js new file mode 100644 index 00000000..e2a08dc3 --- /dev/null +++ b/packages/overlay/index.js @@ -0,0 +1,11 @@ +Component({ + properties: { + show: Boolean + }, + + methods: { + onClickOverlay() { + + } + } +}); diff --git a/packages/overlay/index.json b/packages/overlay/index.json new file mode 100644 index 00000000..467ce294 --- /dev/null +++ b/packages/overlay/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/packages/overlay/index.pcss b/packages/overlay/index.pcss new file mode 100644 index 00000000..e69de29b diff --git a/packages/overlay/index.wxml b/packages/overlay/index.wxml new file mode 100644 index 00000000..bf46ec1c --- /dev/null +++ b/packages/overlay/index.wxml @@ -0,0 +1,5 @@ + diff --git a/packages/toast/README.md b/packages/toast/README.md new file mode 100644 index 00000000..4dad800e --- /dev/null +++ b/packages/toast/README.md @@ -0,0 +1,96 @@ +## Toast 轻提示 + +### 使用指南 + +在 index.json 中引入组件 +```json +"usingComponents": { + "van-toast": "path/to/vant-weapp/dist/toast/index" +} +``` + +### 代码演示 + +#### 文字提示 + +```javascript +const Toast = require('path/to/vant-weapp/dist/toast/index'); + +Toast('我是提示文案,建议不超过十五字~'); +``` + +```html + +``` + +#### 加载提示 + +```javascript +Toast.loading({ + mask: true, + message: '加载中...' +}); +``` + + +#### 成功/失败提示 + +```javascript +Toast.success('成功文案'); +Toast.fail('失败文案'); +``` + + +#### 高级用法 + +```javascript +const toast = Toast.loading({ + duration: 0, // 持续展示 toast + forbidClick: true, // 禁用背景点击 + message: '倒计时 3 秒', + loadingType: 'spinner', + selector: '#custom-selector' +}); + +let second = 3; +const timer = setInterval(() => { + second--; + if (second) { + toast.setData({ + message: `倒计时 ${second} 秒` + }); + } else { + clearInterval(timer); + Toast.clear(); + } +}, 1000); +``` + +```html + +``` + +### 方法 + +| 方法名 | 参数 | 返回值 | 介绍 | +|-----------|-----------|-----------|-------------| +| Toast | `options | message` | toast 实例 | 展示提示 | +| Toast.loading | `options | message` | toast 实例 | 展示加载提示 | +| Toast.success | `options | message` | toast 实例 | 展示成功提示 | +| Toast.fail | `options | message` | toast 实例 | 展示失败提示 | +| Toast.clear | `clearAll` | `void` | 关闭提示 | +| Toast.setDefaultOptions | `options` | `void` | 修改默认配置,对所有 Toast 生效 | +| Toast.resetDefaultOptions | - | `void` | 重置默认配置,对所有 Toast 生效 | + +### Options + +| 参数 | 说明 | 类型 | 默认值 | +|-----------|-----------|-----------|-------------| +| type | 提示类型,可选值为 `loading` `success` `fail` `html` | `String` | `text` | +| position | 位置,可选值为 `top` `middle` `bottom` | `String` | `middle` | +| message | 内容 | `String` | `''` | - | +| mask | 是否显示背景蒙层 | `Boolean` | `false` | +| forbidClick | 是否禁止背景点击 | `Boolean` | `false` | +| loadingType | 加载图标类型, 可选值为 `spinner` | `String` | `circular` | +| duration | 展示时长(ms),值为 0 时,toast 不会消失 | `Number` | `3000` | +| selector | 自定义选择器 | `String` | `van-toast` | diff --git a/packages/toast/index.js b/packages/toast/index.js new file mode 100644 index 00000000..a64e1306 --- /dev/null +++ b/packages/toast/index.js @@ -0,0 +1,32 @@ +import Toast from './toast'; + +Component({ + properties: { + show: Boolean, + mask: Boolean, + message: String, + forbidClick: Boolean, + type: { + type: String, + value: 'text' + }, + loadingType: { + type: String, + value: 'circular' + }, + position: { + type: String, + value: 'middle' + } + }, + + methods: { + clear() { + this.setData({ + show: false + }); + } + } +}); + +export default Toast; diff --git a/packages/toast/index.json b/packages/toast/index.json new file mode 100644 index 00000000..19bf9891 --- /dev/null +++ b/packages/toast/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "usingComponents": { + "van-icon": "../icon/index", + "van-popup": "../popup/index", + "van-loading": "../loading/index" + } +} diff --git a/packages/toast/index.pcss b/packages/toast/index.pcss new file mode 100644 index 00000000..067af85d --- /dev/null +++ b/packages/toast/index.pcss @@ -0,0 +1,69 @@ +@import '../common/style/var.pcss'; + +.van-toast { + top: 50%; + left: 50%; + display: flex; + position: fixed; + color: $white; + font-size: 12px; + line-height: 1.2; + border-radius: 5px; + word-break: break-all; + align-items: center; + justify-content: center; + flex-direction: column; + box-sizing: border-box; + transform: translate(-50%, -50%); + background-color: rgba(0, 0, 0, .7); + z-index: 3001; + + &__overlay { + z-index: 3000; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + + &--mask { + background-color: rgba(0, 0, 0, .7); + } + } + + &--text { + padding: 12px; + min-width: 220px; + } + + &--icon { + width: 120px; + min-height: 120px; + padding: 15px; + + .van-toast__icon { + height: 1em; + font-size: 50px; + } + + .van-toast__text { + font-size: 14px; + padding-top: 10px; + } + } + + &__loading { + margin: 10px 0 5px; + } + + &--top { + top: 50px; + transform: translate(-50%, 0); + } + + &--bottom { + top: auto; + bottom: 50px; + transform: translate(-50%, 0); + } +} diff --git a/packages/toast/index.wxml b/packages/toast/index.wxml new file mode 100644 index 00000000..89565eca --- /dev/null +++ b/packages/toast/index.wxml @@ -0,0 +1,23 @@ + + + + {{ message }} + + + + + + {{ message }} + + diff --git a/packages/toast/toast.js b/packages/toast/toast.js new file mode 100644 index 00000000..c72dab44 --- /dev/null +++ b/packages/toast/toast.js @@ -0,0 +1,68 @@ +import { isObj } from '../utils/index'; + +const defaultOptions = { + type: 'text', + mask: false, + message: '', + show: true, + duration: 3000, + position: 'middle', + forbidClick: false, + loadingType: 'circular', + selector: '#van-toast' +}; +const parseOptions = message => isObj(message) ? message : { message }; + +let queue = []; +let currentOptions = { ...defaultOptions }; + +function Toast(options = {}) { + options = { + ...currentOptions, + ...parseOptions(options) + }; + + const pages = getCurrentPages(); + const ctx = pages[pages.length - 1]; + + const toast = ctx.selectComponent(options.selector); + delete options.selector; + + queue.push(toast); + toast.setData(options); + clearTimeout(toast.timer); + + if (options.duration > 0) { + toast.timer = setTimeout(() => { + toast.clear(); + queue = queue.filter(item => item !== toast); + }, options.duration); + } + + return toast; +}; + +const createMethod = type => options => Toast({ + type, ...parseOptions(options) +}); + +['loading', 'success', 'fail'].forEach(method => { + Toast[method] = createMethod(method); +}); + +Toast.clear = all => { + queue.forEach(toast => { + toast.clear(); + }); + queue = []; +}; + +Toast.setDefaultOptions = options => { + Object.assign(currentOptions, options); +}; + +Toast.resetDefaultOptions = () => { + currentOptions = { ...defaultOptions }; +}; + +export default Toast;