From 1321ba690238f94c97df45202e182eeef8795408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=98=89=E6=B6=B5?= Date: Fri, 17 May 2019 14:16:45 +0800 Subject: [PATCH] [new feature] add image component --- docs/markdown/v2-progress-tracking.md | 3 +- docs/src/demo-entry.js | 1 + docs/src/doc.config.js | 8 ++ docs/src/docs-entry.js | 2 + packages/image/demo/index.vue | 74 +++++++++++++++++ packages/image/en-US.md | 80 ++++++++++++++++++ packages/image/index.js | 81 +++++++++++++++++++ packages/image/index.less | 11 +++ .../test/__snapshots__/demo.spec.js.snap | 35 ++++++++ .../test/__snapshots__/index.spec.js.snap | 3 + packages/image/test/demo.spec.js | 4 + packages/image/test/index.spec.js | 45 +++++++++++ packages/image/zh-CN.md | 80 ++++++++++++++++++ packages/index.less | 1 + packages/index.ts | 3 + 15 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 packages/image/demo/index.vue create mode 100644 packages/image/en-US.md create mode 100644 packages/image/index.js create mode 100644 packages/image/index.less create mode 100644 packages/image/test/__snapshots__/demo.spec.js.snap create mode 100644 packages/image/test/__snapshots__/index.spec.js.snap create mode 100644 packages/image/test/demo.spec.js create mode 100644 packages/image/test/index.spec.js create mode 100644 packages/image/zh-CN.md diff --git a/docs/markdown/v2-progress-tracking.md b/docs/markdown/v2-progress-tracking.md index 277183a23..72816069f 100644 --- a/docs/markdown/v2-progress-tracking.md +++ b/docs/markdown/v2-progress-tracking.md @@ -2,7 +2,7 @@ ## 主要变动 -- 增加三个新组件 +- 增加四个新组件 - 增加数十个 API - 全新的卡片风格文档,更直观 - 所有组件支持通过`less`变量自定义样式 @@ -12,6 +12,7 @@ 在 2.0 版本中,我们按照社区反馈新增以下组件: +- `Image`图片组件 - `Skeleton`骨架屏组件 - `IndexBar`、`IndexAnchor`索引栏组件 - `DropdownMenu`、`DropdownItem`下拉菜单组件 diff --git a/docs/src/demo-entry.js b/docs/src/demo-entry.js index c0a78f54a..d3c4412e9 100644 --- a/docs/src/demo-entry.js +++ b/docs/src/demo-entry.js @@ -22,6 +22,7 @@ export default { 'field': () => wrapper(import('../../packages/field/demo'), 'field'), 'goods-action': () => wrapper(import('../../packages/goods-action/demo'), 'goods-action'), 'icon': () => wrapper(import('../../packages/icon/demo'), 'icon'), + 'image': () => wrapper(import('../../packages/image/demo'), 'image'), 'image-preview': () => wrapper(import('../../packages/image-preview/demo'), 'image-preview'), 'index-bar': () => wrapper(import('../../packages/index-bar/demo'), 'index-bar'), 'lazyload': () => wrapper(import('../../packages/lazyload/demo'), 'lazyload'), diff --git a/docs/src/doc.config.js b/docs/src/doc.config.js index ef5cf8e29..580a26ed7 100644 --- a/docs/src/doc.config.js +++ b/docs/src/doc.config.js @@ -89,6 +89,10 @@ module.exports = { path: '/icon', title: 'Icon 图标' }, + { + path: '/image', + title: 'Image 图片' + }, { path: '/col', title: 'Layout 布局' @@ -408,6 +412,10 @@ module.exports = { path: '/icon', title: 'Icon' }, + { + path: '/image', + title: 'Image' + }, { path: '/col', title: 'Layout' diff --git a/docs/src/docs-entry.js b/docs/src/docs-entry.js index 0651306f9..ec65fd252 100644 --- a/docs/src/docs-entry.js +++ b/docs/src/docs-entry.js @@ -51,6 +51,8 @@ export default { 'goods-action.zh-CN': () => import('../../packages/goods-action/zh-CN.md'), 'icon.en-US': () => import('../../packages/icon/en-US.md'), 'icon.zh-CN': () => import('../../packages/icon/zh-CN.md'), + 'image.en-US': () => import('../../packages/image/en-US.md'), + 'image.zh-CN': () => import('../../packages/image/zh-CN.md'), 'image-preview.en-US': () => import('../../packages/image-preview/en-US.md'), 'image-preview.zh-CN': () => import('../../packages/image-preview/zh-CN.md'), 'index-bar.en-US': () => import('../../packages/index-bar/en-US.md'), diff --git a/packages/image/demo/index.vue b/packages/image/demo/index.vue new file mode 100644 index 000000000..5b8b0dd76 --- /dev/null +++ b/packages/image/demo/index.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/packages/image/en-US.md b/packages/image/en-US.md new file mode 100644 index 000000000..5dd864a86 --- /dev/null +++ b/packages/image/en-US.md @@ -0,0 +1,80 @@ +# Image + +### Install + +``` javascript +import { Image } from 'vant'; + +Vue.use(Image); +``` + +## Usage + +### Basic Usage + +```html + +``` + +### Fit Mode + +```html + +``` + +### Lazy Load + +```html + +``` + +```js +import { Lazyload } from 'vant'; + +Vue.use(Lazyload); +``` + +## API + +### Props + +| Attribute | Description | Type | Default | +|------|------|------|------| +| src | Src | `String` | - | - | +| fit | Fit mode | `String` | `fill` | - | +| alt | Alt | `String` | - | - | +| width | Width | `String | Number` | - | - | +| height | Height | `String | Number` | - | - | +| lazy-load | Whether to enable lazy load,should register [Lazyload](#/en-US/lazyload) component | `Boolean` | `false` | - | + +### fit optional value + +| name | desctription | +|------|------| +| contain | Keep aspect ratio, fully display the long side of the image | +| cover | Keep aspect ratio, fully display the short side of the image, cutting the long side | +| fill | Stretch and resize image to fill the content box | +| none | Not resize image | +| scale-down | Take the smaller of `none` or `contain` | + +### Events + +| Event | Description | Arguments | +|------|------|------| +| click | Triggered when click image | event: Event | +| load | Triggered when image loaded | - | +| error | Triggered when image load failed | - | diff --git a/packages/image/index.js b/packages/image/index.js new file mode 100644 index 000000000..fd062a171 --- /dev/null +++ b/packages/image/index.js @@ -0,0 +1,81 @@ +import { use, isDef, suffixPx } from '../utils'; + +const [sfc, bem] = use('image'); + +export default sfc({ + props: { + src: String, + fit: String, + alt: String, + lazyLoad: Boolean, + width: [String, Number], + height: [String, Number] + }, + + data() { + return { + loading: true, + error: false + }; + }, + + computed: { + style() { + const style = {}; + + if (isDef(this.width)) { + style.width = suffixPx(this.width); + } + + if (isDef(this.height)) { + style.height = suffixPx(this.height); + } + + return style; + } + }, + + methods: { + onLoad(event) { + this.loading = false; + this.$emit('load', event); + }, + + onError(event) { + this.error = true; + this.$emit('error', event); + }, + + onClick(event) { + this.$emit('click', event); + } + }, + + render(h) { + const imgData = { + class: bem('img'), + attrs: { + alt: this.alt + }, + style: { + objectFit: this.fit + }, + on: { + load: this.onLoad, + error: this.onError + } + }; + + const Image = this.lazyLoad ? ( + + ) : ( + + ); + + return ( +
+ {Image} +
+ ); + } +}); diff --git a/packages/image/index.less b/packages/image/index.less new file mode 100644 index 000000000..5f7da3686 --- /dev/null +++ b/packages/image/index.less @@ -0,0 +1,11 @@ +@import '../style/var'; + +.van-image { + display: inline-block; + + &__img { + display: block; + width: 100%; + height: 100%; + } +} diff --git a/packages/image/test/__snapshots__/demo.spec.js.snap b/packages/image/test/__snapshots__/demo.spec.js.snap new file mode 100644 index 000000000..6011ba2db --- /dev/null +++ b/packages/image/test/__snapshots__/demo.spec.js.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders demo correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+
contain
+
+
+
+
cover
+
+
+
+
fill
+
+
+
+
none
+
+
+
+
scale-down
+
+
+
+
+`; diff --git a/packages/image/test/__snapshots__/index.spec.js.snap b/packages/image/test/__snapshots__/index.spec.js.snap new file mode 100644 index 000000000..f66af2b11 --- /dev/null +++ b/packages/image/test/__snapshots__/index.spec.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lazy load 1`] = `
`; diff --git a/packages/image/test/demo.spec.js b/packages/image/test/demo.spec.js new file mode 100644 index 000000000..d647cfabc --- /dev/null +++ b/packages/image/test/demo.spec.js @@ -0,0 +1,4 @@ +import Demo from '../demo'; +import demoTest from '../../../test/demo-test'; + +demoTest(Demo); diff --git a/packages/image/test/index.spec.js b/packages/image/test/index.spec.js new file mode 100644 index 000000000..0e5e936e9 --- /dev/null +++ b/packages/image/test/index.spec.js @@ -0,0 +1,45 @@ + +import { mount } from '../../../test/utils'; +import Image from '..'; + +test('click event', () => { + const wrapper = mount(Image); + + wrapper.trigger('click'); + expect(wrapper.emitted('click')[0][0]).toBeTruthy(); +}); + +test('load event', () => { + const wrapper = mount(Image, { + propsData: { + src: 'https://img.yzcdn.cn/vant/cat.jpeg' + } + }); + + wrapper.find('img').trigger('load'); + + expect(wrapper.emitted('load')[0][0]).toBeTruthy(); +}); + +test('error event', () => { + const wrapper = mount(Image, { + propsData: { + src: 'https://img.yzcdn.cn/vant/cat.jpeg' + } + }); + + wrapper.find('img').trigger('error'); + + expect(wrapper.emitted('error')[0][0]).toBeTruthy(); +}); + +test('lazy load', () => { + const wrapper = mount(Image, { + propsData: { + src: 'https://img.yzcdn.cn/vant/cat.jpeg', + lazyLoad: true + } + }); + + expect(wrapper).toMatchSnapshot(); +}); diff --git a/packages/image/zh-CN.md b/packages/image/zh-CN.md new file mode 100644 index 000000000..91d4aea77 --- /dev/null +++ b/packages/image/zh-CN.md @@ -0,0 +1,80 @@ +# Image 图片 + +### 引入 + +``` javascript +import { Image } from 'vant'; + +Vue.use(Image); +``` + +## 代码演示 + +### 基础用法 + +```html + +``` + +### 缩放模式 + +```html + +``` + +### 图片懒加载 + +```html + +``` + +```js +import { Lazyload } from 'vant'; + +Vue.use(Lazyload); +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | 版本 | +|------|------|------|------|------| +| src | 图片链接 | `String` | - | - | +| fit | 图片裁剪、缩放的模式 | `String` | `fill` | - | +| alt | 替代文本 | `String` | - | - | +| width | 宽度,默认单位为 px | `String | Number` | - | - | +| height | 高度,默认单位为 px | `String | Number` | - | - | +| lazy-load | 是否开启图片懒加载,须配合 [Lazyload](#/zh-CN/lazyload) 组件使用 | `Boolean` | `false` | - | + +### fit 可选值 + +| 名称 | 含义 | +|------|------| +| contain | 保持宽高缩放图片,使图片的长边能完全显示出来 | +| cover | 保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边 | +| fill | 拉伸图片,使图片填满元素 | +| none | 保持图片原有尺寸 | +| scale-down | 取`none`或`contain`中较小的一个 | + +### Events + +| 事件名 | 说明 | 回调参数 | +|------|------|------| +| click | 点击图片时触发 | event: Event | +| load | 图片加载完毕时触发 | - | +| error | 图片加载失败时触发 | - | diff --git a/packages/index.less b/packages/index.less index 975bba9c2..b445ed6a4 100644 --- a/packages/index.less +++ b/packages/index.less @@ -8,6 +8,7 @@ /* common components */ @import './col/index'; @import './row/index'; +@import './image/index'; @import './circle/index'; @import './collapse-item/index'; @import './list/index'; diff --git a/packages/index.ts b/packages/index.ts index 149047efe..fc805b72b 100644 --- a/packages/index.ts +++ b/packages/index.ts @@ -30,6 +30,7 @@ import GoodsAction from './goods-action'; import GoodsActionButton from './goods-action-button'; import GoodsActionIcon from './goods-action-icon'; import Icon from './icon'; +import Image from './image'; import ImagePreview from './image-preview'; import IndexAnchor from './index-anchor'; import IndexBar from './index-bar'; @@ -115,6 +116,7 @@ const components = [ GoodsActionButton, GoodsActionIcon, Icon, + Image, ImagePreview, IndexAnchor, IndexBar, @@ -205,6 +207,7 @@ export { GoodsActionButton, GoodsActionIcon, Icon, + Image, ImagePreview, IndexAnchor, IndexBar,