[new feature] add Toast component (#437)

This commit is contained in:
neverland 2018-08-19 10:41:46 +08:00 committed by GitHub
parent efdfd6691f
commit f6e25a26db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 387 additions and 0 deletions

View File

@ -20,6 +20,7 @@
"pages/switch/index",
"pages/search/index",
"pages/tag/index",
"pages/toast/index",
"pages/tabbar/index",
"pages/tree-select/index"
],

View File

@ -84,6 +84,10 @@ export default [
path: '/actionsheet',
title: 'Actionsheet 上拉菜单'
},
{
path: '/toast',
title: 'Toast 轻提示'
},
{
path: '/notify',
title: 'Notify 消息通知'

View File

@ -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);
}
});

View File

@ -0,0 +1,8 @@
{
"navigationBarTitleText": "Toast 轻提示",
"usingComponents": {
"demo-block": "../../components/demo-block/index",
"van-toast": "../../dist/toast/index",
"van-button": "../../dist/button/index"
}
}

View File

@ -0,0 +1,18 @@
<demo-block title="文字提示" padding>
<van-button bind:tap="showToast">文字提示</van-button>
</demo-block>
<demo-block title="加载提示" padding>
<van-button bind:tap="showLoadingToast">加载提示</van-button>
</demo-block>
<demo-block title="成功/失败提示" padding>
<van-button bind:tap="showSuccessToast" custom-class="demo-margin-right">成功提示</van-button>
<van-button bind:tap="showFailToast">失败提示</van-button>
</demo-block>
<demo-block title="高级用法" padding>
<van-button bind:tap="showCustomizedToast">高级用法</van-button>
</demo-block>
<van-toast id="van-toast" />

View File

11
packages/overlay/index.js Normal file
View File

@ -0,0 +1,11 @@
Component({
properties: {
show: Boolean
},
methods: {
onClickOverlay() {
}
}
});

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

View File

@ -0,0 +1,5 @@
<view
class="overlay-class van-popup__overlay {{ show ? 'van-popup--show' : '' }}"
style="{{ overlayStyle }}"
bind:tap="onClickOverlay"
/>

96
packages/toast/README.md Normal file
View File

@ -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
<van-toast id="van-toast" />
```
#### 加载提示
```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
<van-toast id="custom-selector" />
```
### 方法
| 方法名 | 参数 | 返回值 | 介绍 |
|-----------|-----------|-----------|-------------|
| 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` |

32
packages/toast/index.js Normal file
View File

@ -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;

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
}
}

69
packages/toast/index.pcss Normal file
View File

@ -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);
}
}

23
packages/toast/index.wxml Normal file
View File

@ -0,0 +1,23 @@
<view
wx:if="{{ show && (mask || forbidClick) }}"
class="van-toast__overlay {{ mask ? 'van-toast__overlay--mask' : '' }}"
/>
<view
wx:if="{{ show }}"
class="van-toast van-toast--{{ type === 'text' ? 'text' : 'icon' }} van-toast--{{ position }}"
>
<!-- text only -->
<view wx:if="{{ type === 'text' }}">{{ message }}</view>
<!-- with icon -->
<block wx:else>
<van-loading
wx:if="{{ type === 'loading' }}"
color="white"
type="{{ loadingType }}"
custom-class="van-toast__loading"
/>
<van-icon wx:else class="van-toast__icon" name="{{ type }}" />
<view wx:if="{{ message }}" class="van-toast__text">{{ message }}</view>
</block>
</view>

68
packages/toast/toast.js Normal file
View File

@ -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;