feat: Button component

This commit is contained in:
chenjiahan 2020-07-05 16:19:54 +08:00
parent 0010bfd461
commit 12c167fbbc
11 changed files with 1007 additions and 17 deletions

134
src-next/button/README.md Normal file
View File

@ -0,0 +1,134 @@
# Button
### Install
```js
import Vue from 'vue';
import { Button } from 'vant';
Vue.use(Button);
```
## Usage
### Type
```html
<van-button type="default">Default</van-button>
<van-button type="primary">Primary</van-button>
<van-button type="info">Info</van-button>
<van-button type="danger">Danger</van-button>
<van-button type="warning">Warning</van-button>
```
### Plain
```html
<van-button plain type="primary">Primary</van-button>
<van-button plain type="info">Danger</van-button>
```
### Hairline
```html
<van-button plain hairline type="primary">Hairline</van-button>
<van-button plain hairline type="info">Hairline</van-button>
```
### Disabled
```html
<van-button disabled type="primary">Diabled</van-button>
<van-button disabled type="info">Diabled</van-button>
```
### Loading
```html
<van-button loading type="primary" />
<van-button loading type="primary" loading-type="spinner" />
<van-button loading type="info" loading-text="Loading..." />
```
### Shape
```html
<van-button square type="primary">Square</van-button>
<van-button round type="info">Round</van-button>
```
### Icon
```html
<van-button icon="star-o" type="primary" />
<van-button icon="star-o" type="primary">Button</van-button>
<van-button icon="https://img.yzcdn.cn/vant/logo.png" type="info"
>Button</van-button
>
```
### Size
```html
<van-button type="primary" size="large">Large</van-button>
<van-button type="primary" size="normal">Normal</van-button>
<van-button type="primary" size="small">Small</van-button>
<van-button type="primary" size="mini">Mini</van-button>
```
### Block Element
```html
<van-button type="primary" block>Block Element</van-button>
```
### Route
```html
<van-button type="primary" url="/vant/mobile.html">URL</van-button>
<van-button type="primary" to="index">Vue Router</van-button>
```
### Custom Color
```html
<van-button color="#7232dd">Pure</van-button>
<van-button color="#7232dd" plain>Pure</van-button>
<van-button color="linear-gradient(to right, #4bb0ff, #6149f6)"
>Gradient</van-button
>
```
## API
### Props
| Attribute | Description | Type | Default |
| --- | --- | --- | --- |
| type | Can be set to `primary` `info` `warning` `danger` | _string_ | `default` |
| size | Can be set to `large` `small` `mini` | _string_ | `normal` |
| text | Text | _string_ | - |
| color `v2.1.8` | Color, support linear-gradient | _string_ | - |
| icon | Left Icon | _string_ | - |
| icon-prefix `v2.6.0` | Icon className prefix | _string_ | `van-icon` |
| tag | HTML Tag | _string_ | `button` |
| native-type | Native Type Attribute | _string_ | `''` |
| plain | Whether to be plain button | _boolean_ | `false` |
| block | Whether to set display block | _boolean_ | `false` |
| round | Whether to be round button | _boolean_ | `false` |
| square | Whether to be square button | _boolean_ | `false` |
| disabled | Whether to disable button | _boolean_ | `false` |
| loading | Whether show loading status | _boolean_ | `false` |
| loading-text | Loading text | _string_ | - |
| loading-type | Loading type, can be set to `spinner` | _string_ | `circular` |
| loading-size | Loading icon size | _string_ | `20px` |
| url | Link URL | _string_ | - |
| to | Target route of the link, same as to of vue-router | _string \| object_ | - |
| replace | If true, the navigation will not leave a history record | _boolean_ | `false` |
### Events
| Event | Description | Arguments |
| --- | --- | --- |
| click | Triggered when click button and not disabled or loading | _event: Event_ |
| touchstart | Triggered when touch start | _event: TouchEvent_ |

View File

@ -0,0 +1,157 @@
# Button 按钮
### 引入
```js
import Vue from 'vue';
import { Button } from 'vant';
Vue.use(Button);
```
## 代码演示
### 按钮类型
支持`default``primary``info``warning``danger`五种类型,默认为`default`
```html
<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>
```
### 朴素按钮
通过`plain`属性将按钮设置为朴素按钮,朴素按钮的文字为按钮颜色,背景为白色。
```html
<van-button plain type="primary">朴素按钮</van-button>
<van-button plain type="info">朴素按钮</van-button>
```
### 细边框
设置`hairline`属性可以开启 0.5px 边框,基于伪类实现
```html
<van-button plain hairline type="primary">细边框按钮</van-button>
<van-button plain hairline type="info">细边框按钮</van-button>
```
### 禁用状态
通过`disabled`属性来禁用按钮,禁用状态下按钮不可点击
```html
<van-button disabled type="primary">禁用状态</van-button>
<van-button disabled type="info">禁用状态</van-button>
```
### 加载状态
通过`loading`属性设置按钮为加载状态,加载状态下默认会隐藏按钮文字,可以通过`loading-text`设置加载状态下的文字
```html
<van-button loading type="primary" />
<van-button loading type="primary" loading-type="spinner" />
<van-button loading type="info" loading-text="加载中..." />
```
### 按钮形状
通过`square`设置方形按钮,通过`round`设置圆形按钮
```html
<van-button square type="primary">方形按钮</van-button>
<van-button round type="info">圆形按钮</van-button>
```
### 图标按钮
通过`icon`属性设置按钮图标,支持 Icon 组件里的所有图标,也可以传入图标 URL
```html
<van-button icon="star-o" type="primary" />
<van-button icon="star-o" type="primary">按钮</van-button>
<van-button icon="https://img.yzcdn.cn/vant/logo.png" type="info"
>按钮</van-button
>
```
### 按钮尺寸
支持`large``normal``small``mini`四种尺寸,默认为`normal`
```html
<van-button type="primary" size="large">大号按钮</van-button>
<van-button type="primary" size="normal">普通按钮</van-button>
<van-button type="primary" size="small">小型按钮</van-button>
<van-button type="primary" size="mini">迷你按钮</van-button>
```
### 块级元素
按钮在默认情况下为行内块级元素,通过`block`属性可以将按钮的元素类型设置为块级元素
```html
<van-button type="primary" block>块级元素</van-button>
```
### 页面导航
可以通过`url`属性进行 URL 跳转,或通过`to`属性进行路由跳转
```html
<van-button type="primary" url="/vant/mobile.html">URL 跳转</van-button>
<van-button type="primary" to="index">路由跳转</van-button>
```
### 自定义颜色
通过`color`属性可以自定义按钮的颜色
```html
<van-button color="#7232dd">单色按钮</van-button>
<van-button color="#7232dd" plain>单色按钮</van-button>
<van-button color="linear-gradient(to right, #4bb0ff, #6149f6)"
>渐变色按钮</van-button
>
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 类型,可选值为 `primary` `info` `warning` `danger` | _string_ | `default` |
| size | 尺寸,可选值为 `large` `small` `mini` | _string_ | `normal` |
| text | 按钮文字 | _string_ | - |
| color `v2.1.8` | 按钮颜色,支持传入`linear-gradient`渐变色 | _string_ | - |
| icon | 左侧[图标名称](#/zh-CN/icon)或图片链接 | _string_ | - |
| icon-prefix `v2.6.0` | 图标类名前缀,同 Icon 组件的 [class-prefix 属性](#/zh-CN/icon#props) | _string_ | `van-icon` |
| tag | 根节点的 HTML 标签 | _string_ | `button` |
| native-type | 原生 button 标签的 type 属性 | _string_ | - |
| block | 是否为块级元素 | _boolean_ | `false` |
| plain | 是否为朴素按钮 | _boolean_ | `false` |
| square | 是否为方形按钮 | _boolean_ | `false` |
| round | 是否为圆形按钮 | _boolean_ | `false` |
| disabled | 是否禁用按钮 | _boolean_ | `false` |
| hairline | 是否使用 0.5px 边框 | _boolean_ | `false` |
| loading | 是否显示为加载状态 | _boolean_ | `false` |
| loading-text | 加载状态提示文字 | _string_ | - |
| loading-type | [加载图标类型](#/zh-CN/loading),可选值为`spinner` | _string_ | `circular` |
| loading-size | 加载图标大小 | _string_ | `20px` |
| url | 点击后跳转的链接地址 | _string_ | - |
| to | 点击后跳转的目标路由对象,同 vue-router 的 [to 属性](https://router.vuejs.org/zh/api/#to) | _string \| object_ | - |
| replace | 是否在跳转时替换当前页面历史 | _boolean_ | `false` |
### Events
| 事件名 | 说明 | 回调参数 |
| ---------- | ---------------------------------------- | ------------------- |
| click | 点击按钮,且按钮状态不为加载或禁用时触发 | _event: Event_ |
| touchstart | 开始触摸按钮时触发 | _event: TouchEvent_ |

View File

@ -0,0 +1,173 @@
<template>
<demo-section>
<demo-block :title="t('type')">
<div class="demo-button-row">
<van-button type="default">{{ t('default') }}</van-button>
<van-button type="primary">{{ t('primary') }}</van-button>
<van-button type="info">{{ t('info') }}</van-button>
</div>
<van-button type="danger">{{ t('danger') }}</van-button>
<van-button type="warning">{{ t('warning') }}</van-button>
</demo-block>
<demo-block :title="t('plain')">
<van-button plain type="primary" :text="t('plain')" />
<van-button plain type="info" :text="t('plain')" />
</demo-block>
<demo-block :title="t('hairline')">
<van-button plain hairline type="primary" :text="t('hairlineButton')" />
<van-button plain hairline type="info" :text="t('hairlineButton')" />
</demo-block>
<demo-block :title="t('disabled')">
<van-button disabled type="primary" :text="t('disabled')" />
<van-button disabled type="info" :text="t('disabled')" />
</demo-block>
<demo-block :title="t('loadingStatus')">
<van-button loading type="primary" />
<van-button loading type="primary" loading-type="spinner" />
<van-button loading :loading-text="t('loadingText')" type="info" />
</demo-block>
<demo-block :title="t('shape')">
<van-button type="primary" square :text="t('square')" />
<van-button type="info" round :text="t('round')" />
</demo-block>
<demo-block :title="t('icon')">
<van-button type="primary" icon="star-o" />
<van-button type="primary" icon="star-o" :text="t('button')" />
<van-button
plain
type="primary"
icon="https://img.yzcdn.cn/vant/logo.png"
:text="t('button')"
/>
</demo-block>
<demo-block :title="t('size')">
<van-button type="primary" size="large">{{ t('large') }}</van-button>
<van-button type="primary" size="normal">{{ t('normal') }}</van-button>
<van-button type="primary" size="small">{{ t('small') }}</van-button>
<van-button type="primary" size="mini">{{ t('mini') }}</van-button>
</demo-block>
<demo-block :title="t('blockElement')">
<van-button type="primary" block>{{ t('blockElement') }}</van-button>
</demo-block>
<demo-block v-if="!isWeapp" :title="t('router')">
<van-button
:text="t('urlRoute')"
type="primary"
url="/vant/mobile.html"
/>
<van-button :text="t('vueRoute')" type="primary" to="index" />
</demo-block>
<demo-block :title="t('customColor')">
<van-button color="#7232dd" :text="t('pure')" />
<van-button plain color="#7232dd" :text="t('pure')" />
<van-button
color="linear-gradient(to right, #4bb0ff, #6149f6)"
:text="t('gradient')"
/>
</demo-block>
</demo-section>
</template>
<script>
export default {
i18n: {
'zh-CN': {
type: '按钮类型',
size: '按钮尺寸',
icon: '图标按钮',
loading: '加载状态',
shape: '按钮形状',
default: '默认按钮',
primary: '主要按钮',
info: '信息按钮',
danger: '危险按钮',
warning: '警告按钮',
large: '大号按钮',
normal: '普通按钮',
small: '小型按钮',
mini: '迷你按钮',
plain: '朴素按钮',
square: '方形按钮',
round: '圆形按钮',
hairline: '细边框',
hairlineButton: '细边框按钮',
loadingText: '加载中...',
router: '页面导航',
urlRoute: 'URL 跳转',
vueRoute: '路由跳转',
customColor: '自定义颜色',
pure: '单色按钮',
gradient: '渐变色按钮',
blockElement: '块级元素',
},
'en-US': {
type: 'Type',
size: 'Size',
icon: 'Icon',
loading: 'Loading',
shape: 'Shape',
default: 'Default',
primary: 'Primary',
info: 'Info',
danger: 'Danger',
warning: 'Warning',
large: 'Large',
normal: 'Normal',
small: 'Small',
mini: 'Mini',
plain: 'Plain',
square: 'Square',
round: 'Round',
hairline: 'Hairline',
hairlineButton: 'Hairline',
loadingText: 'Loading...',
router: 'Router',
urlRoute: 'URL',
vueRoute: 'Vue Router',
customColor: 'Custom Color',
pure: 'Pure',
gradient: 'Gradient',
blockElement: 'Block Element',
},
},
};
</script>
<style lang="less">
@import '../../style/var';
.demo-button {
.van-button {
&--large {
margin-bottom: @padding-md;
}
&--small,
&--normal:not(:last-child) {
margin-right: @padding-md;
}
}
.van-doc-demo-block {
padding: 0 @padding-md;
}
.van-doc-demo-block__title {
padding-left: 0;
}
&-row {
margin-bottom: @padding-sm;
}
}
</style>

147
src-next/button/index.js Normal file
View File

@ -0,0 +1,147 @@
// Utils
import { createNamespace } from '../utils';
import { BORDER_SURROUND, WHITE } from '../utils/constant';
import { routeProps, route } from '../utils/router';
// Components
import Icon from '../icon';
import Loading from '../loading';
const [createComponent, bem] = createNamespace('button');
export default createComponent({
props: {
...routeProps,
text: String,
icon: String,
color: String,
block: Boolean,
plain: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
iconPrefix: String,
nativeType: String,
loadingText: String,
loadingType: String,
tag: {
type: String,
default: 'button',
},
type: {
type: String,
default: 'default',
},
size: {
type: String,
default: 'normal',
},
loadingSize: {
type: String,
default: '20px',
},
},
methods: {
onClick() {
if (!this.loading && !this.disabled) {
this.$emit('click', event);
route(this.$router, this);
}
},
onTouchstart(event) {
this.$emit('touchstart', event);
},
genContent() {
const Content = [];
if (this.loading) {
Content.push(
<Loading
class={bem('loading')}
size={this.loadingSize}
type={this.loadingType}
color="currentColor"
/>
);
} else if (this.icon) {
Content.push(
<Icon
name={this.icon}
class={bem('icon')}
classPrefix={this.iconPrefix}
/>
);
}
let text;
if (this.loading) {
text = this.loadingText;
} else {
text = this.$slots.default ? this.$slots.default() : this.text;
}
if (text) {
Content.push(<span class={bem('text')}>{text}</span>);
}
return Content;
},
},
render() {
const { tag, type, color, plain, disabled, loading, hairline } = this;
const style = {};
if (color) {
style.color = plain ? color : WHITE;
if (!plain) {
// Use background instead of backgroundColor to make linear-gradient work
style.background = color;
}
// hide border when color is linear-gradient
if (color.indexOf('gradient') !== -1) {
style.border = 0;
} else {
style.borderColor = color;
}
}
const classes = [
bem([
type,
this.size,
{
plain,
loading,
disabled,
hairline,
block: this.block,
round: this.round,
square: this.square,
},
]),
{ [BORDER_SURROUND]: hairline },
];
return (
<tag
style={style}
class={classes}
type={this.nativeType}
disabled={disabled}
onClick={this.onClick}
onTouchstart={this.onTouchstart}
>
<div class={bem('content')}>{this.genContent()}</div>
</tag>
);
},
});

183
src-next/button/index.less Normal file
View File

@ -0,0 +1,183 @@
@import '../style/var';
.van-button {
position: relative;
display: inline-block;
box-sizing: border-box;
height: @button-default-height;
margin: 0;
padding: 0;
font-size: @button-default-font-size;
line-height: @button-default-line-height;
text-align: center;
border-radius: @button-border-radius;
cursor: pointer;
transition: opacity @animation-duration-fast;
-webkit-appearance: none;
&::before {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
background-color: @black;
border: inherit;
border-color: @black;
border-radius: inherit; /* inherit parent's border radius */
transform: translate(-50%, -50%);
opacity: 0;
content: ' ';
}
&:active::before {
opacity: 0.1;
}
&--loading,
&--disabled {
&::before {
display: none;
}
}
&--default {
color: @button-default-color;
background-color: @button-default-background-color;
border: @button-border-width solid @button-default-border-color;
}
&--primary {
color: @button-primary-color;
background-color: @button-primary-background-color;
border: @button-border-width solid @button-primary-border-color;
}
&--info {
color: @button-info-color;
background-color: @button-info-background-color;
border: @button-border-width solid @button-info-border-color;
}
&--danger {
color: @button-danger-color;
background-color: @button-danger-background-color;
border: @button-border-width solid @button-danger-border-color;
}
&--warning {
color: @button-warning-color;
background-color: @button-warning-background-color;
border: @button-border-width solid @button-warning-border-color;
}
&--plain {
background-color: @button-plain-background-color;
&.van-button--primary {
color: @button-primary-background-color;
}
&.van-button--info {
color: @button-info-background-color;
}
&.van-button--danger {
color: @button-danger-background-color;
}
&.van-button--warning {
color: @button-warning-background-color;
}
}
&--large {
width: 100%;
height: @button-large-height;
}
&--normal {
padding: 0 15px;
font-size: @button-normal-font-size;
}
&--small {
height: @button-small-height;
padding: 0 @padding-xs;
font-size: @button-small-font-size;
}
&__loading {
color: inherit;
font-size: inherit;
}
&--mini {
height: @button-mini-height;
padding: 0 @padding-base;
font-size: @button-mini-font-size;
& + .van-button--mini {
margin-left: @padding-base;
}
}
&--block {
display: block;
width: 100%;
}
&--disabled {
cursor: not-allowed;
opacity: @button-disabled-opacity;
}
&--loading {
cursor: default;
}
&--round {
border-radius: @button-round-border-radius;
}
&--square {
border-radius: 0;
}
// align-items are ignored when flex container is a button in legacy safari
// see: https://bugs.webkit.org/show_bug.cgi?id=169700
&__content {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
&__icon {
min-width: 1em;
font-size: 1.2em;
line-height: inherit;
}
&__icon + &__text,
&__loading + &__text {
margin-left: 5px;
}
&--hairline {
border-width: 0;
&::after {
border-color: inherit;
border-radius: @button-border-radius * 2;
}
&.van-button--round::after {
border-radius: @button-round-border-radius;
}
&.van-button--square::after {
border-radius: 0;
}
}
}

View File

@ -0,0 +1,86 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders demo correctly 1`] = `
<div>
<div>
<div class="demo-button-row"><button class="van-button van-button--default van-button--normal">
<div class="van-button__content"><span class="van-button__text">默认按钮</span></div>
</button> <button class="van-button van-button--primary van-button--normal">
<div class="van-button__content"><span class="van-button__text">主要按钮</span></div>
</button> <button class="van-button van-button--info van-button--normal">
<div class="van-button__content"><span class="van-button__text">信息按钮</span></div>
</button></div> <button class="van-button van-button--danger van-button--normal">
<div class="van-button__content"><span class="van-button__text">危险按钮</span></div>
</button> <button class="van-button van-button--warning van-button--normal">
<div class="van-button__content"><span class="van-button__text">警告按钮</span></div>
</button>
</div>
<div><button class="van-button van-button--primary van-button--normal van-button--plain">
<div class="van-button__content"><span class="van-button__text">朴素按钮</span></div>
</button> <button class="van-button van-button--info van-button--normal van-button--plain">
<div class="van-button__content"><span class="van-button__text">朴素按钮</span></div>
</button></div>
<div><button class="van-button van-button--primary van-button--normal van-button--plain van-button--hairline van-hairline--surround">
<div class="van-button__content"><span class="van-button__text">细边框按钮</span></div>
</button> <button class="van-button van-button--info van-button--normal van-button--plain van-button--hairline van-hairline--surround">
<div class="van-button__content"><span class="van-button__text">细边框按钮</span></div>
</button></div>
<div><button disabled="disabled" class="van-button van-button--primary van-button--normal van-button--disabled">
<div class="van-button__content"><span class="van-button__text">禁用状态</span></div>
</button> <button disabled="disabled" class="van-button van-button--info van-button--normal van-button--disabled">
<div class="van-button__content"><span class="van-button__text">禁用状态</span></div>
</button></div>
<div><button class="van-button van-button--primary van-button--normal van-button--loading">
<div class="van-button__content">
<div class="van-loading van-loading--circular van-button__loading"><span class="van-loading__spinner van-loading__spinner--circular" style="color: currentColor; width: 20px; height: 20px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
</div>
</button> <button class="van-button van-button--primary van-button--normal van-button--loading">
<div class="van-button__content">
<div class="van-loading van-loading--spinner van-button__loading"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: currentColor; width: 20px; height: 20px;"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</button> <button class="van-button van-button--info van-button--normal van-button--loading">
<div class="van-button__content">
<div class="van-loading van-loading--circular van-button__loading"><span class="van-loading__spinner van-loading__spinner--circular" style="color: currentColor; width: 20px; height: 20px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div><span class="van-button__text">加载中...</span>
</div>
</button></div>
<div><button class="van-button van-button--primary van-button--normal van-button--square">
<div class="van-button__content"><span class="van-button__text">方形按钮</span></div>
</button> <button class="van-button van-button--info van-button--normal van-button--round">
<div class="van-button__content"><span class="van-button__text">圆形按钮</span></div>
</button></div>
<div><button class="van-button van-button--primary van-button--normal">
<div class="van-button__content"><i class="van-icon van-icon-star-o van-button__icon">
<!----></i></div>
</button> <button class="van-button van-button--primary van-button--normal">
<div class="van-button__content"><i class="van-icon van-icon-star-o van-button__icon">
<!----></i><span class="van-button__text">按钮</span></div>
</button> <button class="van-button van-button--primary van-button--normal van-button--plain">
<div class="van-button__content"><i class="van-icon van-button__icon"><img src="https://img.yzcdn.cn/vant/logo.png" class="van-icon__image">
<!----></i><span class="van-button__text">按钮</span></div>
</button></div>
<div><button class="van-button van-button--primary van-button--large">
<div class="van-button__content"><span class="van-button__text">大号按钮</span></div>
</button> <button class="van-button van-button--primary van-button--normal">
<div class="van-button__content"><span class="van-button__text">普通按钮</span></div>
</button> <button class="van-button van-button--primary van-button--small">
<div class="van-button__content"><span class="van-button__text">小型按钮</span></div>
</button> <button class="van-button van-button--primary van-button--mini">
<div class="van-button__content"><span class="van-button__text">迷你按钮</span></div>
</button></div>
<div><button class="van-button van-button--primary van-button--normal van-button--block">
<div class="van-button__content"><span class="van-button__text">块级元素</span></div>
</button></div>
<div><button class="van-button van-button--primary van-button--normal">
<div class="van-button__content"><span class="van-button__text">URL 跳转</span></div>
</button> <button class="van-button van-button--primary van-button--normal">
<div class="van-button__content"><span class="van-button__text">路由跳转</span></div>
</button></div>
<div><button class="van-button van-button--default van-button--normal" style="color: rgb(255, 255, 255); background: rgb(114, 50, 221); border-color: #7232dd;">
<div class="van-button__content"><span class="van-button__text">单色按钮</span></div>
</button> <button class="van-button van-button--default van-button--normal van-button--plain" style="color: rgb(114, 50, 221); border-color: #7232dd;">
<div class="van-button__content"><span class="van-button__text">单色按钮</span></div>
</button> <button class="van-button van-button--default van-button--normal" style="color: rgb(255, 255, 255); border: 0px;">
<div class="van-button__content"><span class="van-button__text">渐变色按钮</span></div>
</button></div>
</div>
`;

View File

@ -0,0 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`icon-prefix prop 1`] = `
<button class="van-button van-button--default van-button--normal">
<div class="van-button__content"><i class="my-icon my-icon-success van-button__icon">
<!----></i></div>
</button>
`;
exports[`loading-size prop 1`] = `
<button class="van-button van-button--default van-button--normal van-button--loading">
<div class="van-button__content">
<div class="van-loading van-loading--circular van-button__loading"><span class="van-loading__spinner van-loading__spinner--circular" style="color: currentColor; width: 10px; height: 10px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
</div>
</button>
`;

View File

@ -0,0 +1,4 @@
import Demo from '../demo';
import { snapshotDemo } from '../../../test/demo';
snapshotDemo(Demo);

View File

@ -0,0 +1,95 @@
import { mount } from '../../../test';
import Button from '..';
test('loading-size prop', () => {
const wrapper = mount(Button, {
propsData: {
loading: true,
loadingSize: '10px',
},
});
expect(wrapper).toMatchSnapshot();
});
test('click event', () => {
const onClick = jest.fn();
const wrapper = mount(Button, {
context: {
on: {
click: onClick,
},
},
});
wrapper.trigger('click');
expect(onClick).toHaveBeenCalled();
});
test('not trigger click event when disabled', () => {
const onClick = jest.fn();
const wrapper = mount(Button, {
propsData: {
disabled: true,
},
context: {
on: {
click: onClick,
},
},
});
wrapper.trigger('click');
expect(onClick).toHaveBeenCalledTimes(0);
});
test('not trigger click event when loading', () => {
const onClick = jest.fn();
const wrapper = mount(Button, {
propsData: {
loading: true,
},
context: {
on: {
click: onClick,
},
},
});
wrapper.trigger('click');
expect(onClick).toHaveBeenCalledTimes(0);
});
test('touchstart event', () => {
const onTouchstart = jest.fn();
const wrapper = mount(Button, {
context: {
on: {
touchstart: onTouchstart,
},
},
});
wrapper.trigger('touchstart');
expect(onTouchstart).toHaveBeenCalled();
});
test('hide border when color is gradient', () => {
const wrapper = mount(Button, {
propsData: {
color: 'linear-gradient(#000, #fff)',
},
});
expect(wrapper.element.style.border).toEqual('0px');
});
test('icon-prefix prop', () => {
const wrapper = mount(Button, {
propsData: {
icon: 'success',
iconPrefix: 'my-icon',
},
});
expect(wrapper).toMatchSnapshot();
});

View File

@ -2,12 +2,11 @@
* Vue Router support * Vue Router support
*/ */
import { RenderContext } from 'vue/types'; import type { Router, RouteLocation } from 'vue-router';
import VueRouter, { RawLocation } from 'vue-router/types';
export type RouteConfig = { export type RouteConfig = {
url?: string; url?: string;
to?: RawLocation; to?: RouteLocation;
replace?: boolean; replace?: boolean;
}; };
@ -19,7 +18,7 @@ function isRedundantNavigation(err: Error) {
); );
} }
export function route(router: VueRouter, config: RouteConfig) { export function route(router: Router, config: RouteConfig) {
const { to, url, replace } = config; const { to, url, replace } = config;
if (to && router) { if (to && router) {
const promise = router[replace ? 'replace' : 'push'](to); const promise = router[replace ? 'replace' : 'push'](to);
@ -37,14 +36,10 @@ export function route(router: VueRouter, config: RouteConfig) {
} }
} }
export function functionalRoute(context: RenderContext) {
route(context.parent && context.parent.$router, context.props);
}
export type RouteProps = { export type RouteProps = {
url?: string; url?: string;
replace?: boolean; replace?: boolean;
to?: RawLocation; to?: RouteLocation;
}; };
export const routeProps = { export const routeProps = {

View File

@ -78,10 +78,10 @@ module.exports = {
{ {
title: '基础组件', title: '基础组件',
items: [ items: [
// { {
// path: 'button', path: 'button',
// title: 'Button 按钮', title: 'Button 按钮',
// }, },
// { // {
// path: 'cell', // path: 'cell',
// title: 'Cell 单元格', // title: 'Cell 单元格',
@ -425,10 +425,10 @@ module.exports = {
{ {
title: 'Basic Components', title: 'Basic Components',
items: [ items: [
// { {
// path: 'button', path: 'button',
// title: 'Button', title: 'Button',
// }, },
// { // {
// path: 'cell', // path: 'cell',
// title: 'Cell', // title: 'Cell',