diff --git a/src/empty/README.md b/src/empty/README.md new file mode 100644 index 000000000..96b16f395 --- /dev/null +++ b/src/empty/README.md @@ -0,0 +1,80 @@ +# Empty + +### Install + +```js +import Vue from 'vue'; +import { Empty } from 'vant'; + +Vue.use(Empty); +``` + +## Usage + +### Basic Usage + +```html + +``` + +### Image Type + +Use the image prop to display different placeholder images + +```html + + + + + + +``` + +### Custom Image + +```html + + + +``` + +### Bottom Content + +```html + + + Button + + + + +``` + +## API + +### Props + +| Attribute | Description | Type | Default | +|------|------|------|------| +| image | Image type,can be set to `error` `network` `search` or image URL | *string* | `default` | +| description | Desciption | *string* | - | + +### Slots + +| Name | Description | +|------|------| +| default | Custom bottom content | +| image | Custom image | +| description | Custom description | diff --git a/src/empty/README.zh-CN.md b/src/empty/README.zh-CN.md new file mode 100644 index 000000000..188e0740e --- /dev/null +++ b/src/empty/README.zh-CN.md @@ -0,0 +1,89 @@ +# Empty 空状态 + +### 介绍 + +空状态时的占位提示,2.6 版本开始支持此组件 + +### 引入 + +```js +import Vue from 'vue'; +import { Empty } from 'vant'; + +Vue.use(Empty); +``` + +## 代码演示 + +### 基本用法 + +```html + +``` + +### 图片类型 + +Empty 组件内置了多种占位图片类型,可以在不同业务场景下使用 + +```html + + + + + + +``` + +### 自定义图片 + +需要自定义图片时,可以在 image 属性中传入任意图片 URL + +```html + + + +``` + +### 底部内容 + +通过默认插槽可以在 Empty 组件的下方插入内容 + +```html + + + 按钮 + + + + +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +|------|------|------|------| +| image | 图片类型,可选值为 `error` `network` `search`,支持传入图片 URL | *string* | `default` | +| description | 图片下方的描述文字 | *string* | - | + +### Slots + +| 名称 | 说明 | +|------|------| +| default | 自定义底部内容 | +| image | 自定义图标 | +| description | 自定义描述文字 | diff --git a/src/empty/demo/index.vue b/src/empty/demo/index.vue new file mode 100644 index 000000000..b712d4b96 --- /dev/null +++ b/src/empty/demo/index.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/empty/index.js b/src/empty/index.js new file mode 100644 index 000000000..8300e09cd --- /dev/null +++ b/src/empty/index.js @@ -0,0 +1,58 @@ +import { createNamespace } from '../utils'; + +const [createComponent, bem] = createNamespace('empty'); + +const PRESETS = ['error', 'search', 'default', 'network']; + +export default createComponent({ + props: { + description: String, + image: { + type: String, + default: 'default', + }, + }, + + computed: { + url() { + if (PRESETS.indexOf(this.image) !== -1) { + return `https://img.yzcdn.cn/vant/empty-image-${this.image}.png`; + } + + return this.image; + }, + }, + + methods: { + genImage() { + const image = this.slots('image') || ; + return
{image}
; + }, + + genDescription() { + const description = this.slots('description') || this.description; + + if (description) { + return

{description}

; + } + }, + + genBottom() { + const slot = this.slots(); + + if (slot) { + return
{slot}
; + } + }, + }, + + render() { + return ( +
+ {this.genImage()} + {this.genDescription()} + {this.genBottom()} +
+ ); + }, +}); diff --git a/src/empty/index.less b/src/empty/index.less new file mode 100644 index 000000000..2a28d2b86 --- /dev/null +++ b/src/empty/index.less @@ -0,0 +1,32 @@ +@import '../style/var'; + +.van-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + box-sizing: border-box; + padding: @empty-padding; + + &__image { + width: @empty-image-size; + height: @empty-image-size; + + img { + width: 100%; + height: 100%; + } + } + + &__description { + margin-top: @empty-description-margin-top; + padding: @empty-description-padding; + color: @empty-description-color; + font-size: @empty-description-font-size; + line-height: @empty-description-line-height; + } + + &__bottom { + margin-top: @empty-bottom-margin-top; + } +} diff --git a/src/empty/test/__snapshots__/demo.spec.js.snap b/src/empty/test/__snapshots__/demo.spec.js.snap new file mode 100644 index 000000000..3771c5aba --- /dev/null +++ b/src/empty/test/__snapshots__/demo.spec.js.snap @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders demo correctly 1`] = ` +
+
+
+
+

描述文字

+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+

描述文字

+
+
+ + +
+
+
+
+
+
+

描述文字

+
+
+
+
+
+

描述文字

+
+
+
+
+`; diff --git a/src/empty/test/__snapshots__/index.spec.js.snap b/src/empty/test/__snapshots__/index.spec.js.snap new file mode 100644 index 000000000..3f2244c96 --- /dev/null +++ b/src/empty/test/__snapshots__/index.spec.js.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`description slot 1`] = ` +
+
+

Custom description

+
+`; + +exports[`image slot 1`] = ` +
+
Custom Image
+
+`; diff --git a/src/empty/test/demo.spec.js b/src/empty/test/demo.spec.js new file mode 100644 index 000000000..5c70922b5 --- /dev/null +++ b/src/empty/test/demo.spec.js @@ -0,0 +1,4 @@ +import Demo from '../demo'; +import { snapshotDemo } from '../../../test/demo'; + +snapshotDemo(Demo); diff --git a/src/empty/test/index.spec.js b/src/empty/test/index.spec.js new file mode 100644 index 000000000..7dd7cb4ff --- /dev/null +++ b/src/empty/test/index.spec.js @@ -0,0 +1,22 @@ +import Empty from '..'; +import { mount } from '../../../test'; + +test('image slot', () => { + const wrapper = mount(Empty, { + scopedSlots: { + image: () => 'Custom Image', + }, + }); + + expect(wrapper).toMatchSnapshot(); +}); + +test('description slot', () => { + const wrapper = mount(Empty, { + scopedSlots: { + description: () => 'Custom description', + }, + }); + + expect(wrapper).toMatchSnapshot(); +}); diff --git a/src/style/var.less b/src/style/var.less index ada8b4c0e..13810ad62 100644 --- a/src/style/var.less +++ b/src/style/var.less @@ -333,6 +333,16 @@ @dropdown-menu-content-max-height: 80%; @dropdown-item-z-index: 10; +// Empty +@empty-padding: @padding-xl 0; +@empty-image-size: 160px; +@empty-description-margin-top: @padding-md; +@empty-description-padding: 0 60px; +@empty-description-color: @gray-6; +@empty-description-font-size: 14px; +@empty-description-line-height: 20px; +@empty-bottom-margin-top: 24px; + // Field @field-label-width: 90px; @field-input-text-color: @text-color; diff --git a/types/index.d.ts b/types/index.d.ts index 96db95695..447df1a91 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -45,6 +45,7 @@ export class CouponCell extends VanComponent {} export class CouponList extends VanComponent {} export class Divider extends VanComponent {} export class DropdownMenu extends VanComponent {} +export class Empty extends VanComponent {} export class Grid extends VanComponent {} export class GridItem extends VanComponent {} export class GoodsAction extends VanComponent {} diff --git a/vant.config.js b/vant.config.js index bb0c6cbc3..598f28c55 100644 --- a/vant.config.js +++ b/vant.config.js @@ -232,6 +232,10 @@ module.exports = { path: 'divider', title: 'Divider 分割线', }, + { + path: 'empty', + title: 'Empty 空状态', + }, { path: 'image-preview', title: 'ImagePreview 图片预览', @@ -575,6 +579,10 @@ module.exports = { path: 'divider', title: 'Divider', }, + { + path: 'empty', + title: 'Empty', + }, { path: 'image-preview', title: 'ImagePreview',