[improvement] rename packages dir to src (#3659)

This commit is contained in:
neverland
2019-06-27 11:25:57 +08:00
committed by GitHub
parent 8489918dca
commit 75c79b7044
619 changed files with 21 additions and 21 deletions
+305
View File
@@ -0,0 +1,305 @@
import { createNamespace, isServer } from '../utils';
import { range } from '../utils/format/number';
import { preventDefault } from '../utils/dom/event';
import { PopupMixin } from '../mixins/popup';
import { TouchMixin } from '../mixins/touch';
import Swipe from '../swipe';
import SwipeItem from '../swipe-item';
const [createComponent, bem] = createNamespace('image-preview');
function getDistance(touches) {
return Math.sqrt(
Math.abs(
(touches[0].clientX - touches[1].clientX) *
(touches[0].clientY - touches[1].clientY)
)
);
}
export default createComponent({
mixins: [PopupMixin, TouchMixin],
props: {
images: Array,
className: null,
lazyLoad: Boolean,
asyncClose: Boolean,
startPosition: Number,
showIndicators: Boolean,
closeOnPopstate: Boolean,
loop: {
type: Boolean,
default: true
},
overlay: {
type: Boolean,
default: true
},
showIndex: {
type: Boolean,
default: true
},
minZoom: {
type: Number,
default: 1 / 3
},
maxZoom: {
type: Number,
default: 3
},
overlayClass: {
type: String,
default: 'van-image-preview__overlay'
},
closeOnClickOverlay: {
type: Boolean,
default: true
}
},
data() {
this.bindStatus = false;
return {
scale: 1,
moveX: 0,
moveY: 0,
moving: false,
zooming: false,
active: 0
};
},
computed: {
imageStyle() {
const { scale } = this;
const style = {
transition: this.zooming || this.moving ? '' : '.3s all'
};
if (scale !== 1) {
style.transform = `scale3d(${scale}, ${scale}, 1) translate(${this.moveX /
scale}px, ${this.moveY / scale}px)`;
}
return style;
}
},
watch: {
value() {
this.active = this.startPosition;
},
startPosition(active) {
this.active = active;
},
closeOnPopstate: {
handler(val) {
this.handlePopstate(val);
},
immediate: true
}
},
methods: {
handlePopstate(bind) {
/* istanbul ignore if */
if (isServer) {
return;
}
if (this.bindStatus !== bind) {
this.bindStatus = bind;
const action = bind ? 'add' : 'remove';
window[`${action}EventListener`]('popstate', this.close);
}
},
onWrapperTouchStart() {
this.touchStartTime = new Date();
},
onWrapperTouchEnd(event) {
preventDefault(event);
const deltaTime = new Date() - this.touchStartTime;
const { offsetX = 0, offsetY = 0 } = this.$refs.swipe || {};
// prevent long tap to close component
if (deltaTime < 300 && offsetX < 10 && offsetY < 10) {
const index = this.active;
this.resetScale();
this.$emit('close', {
index,
url: this.images[index]
});
if (!this.asyncClose) {
this.$emit('input', false);
}
}
},
startMove(event) {
const image = event.currentTarget;
const rect = image.getBoundingClientRect();
const winWidth = window.innerWidth;
const winHeight = window.innerHeight;
this.touchStart(event);
this.moving = true;
this.startMoveX = this.moveX;
this.startMoveY = this.moveY;
this.maxMoveX = Math.max(0, (rect.width - winWidth) / 2);
this.maxMoveY = Math.max(0, (rect.height - winHeight) / 2);
},
startZoom(event) {
this.moving = false;
this.zooming = true;
this.startScale = this.scale;
this.startDistance = getDistance(event.touches);
},
onImageTouchStart(event) {
const { touches } = event;
const { offsetX = 0 } = this.$refs.swipe || {};
if (touches.length === 1 && this.scale !== 1) {
this.startMove(event);
} /* istanbul ignore else */ else if (touches.length === 2 && !offsetX) {
this.startZoom(event);
}
},
onImageTouchMove(event) {
const { touches } = event;
if (this.moving || this.zooming) {
preventDefault(event, true);
}
if (this.moving) {
this.touchMove(event);
const moveX = this.deltaX + this.startMoveX;
const moveY = this.deltaY + this.startMoveY;
this.moveX = range(moveX, -this.maxMoveX, this.maxMoveX);
this.moveY = range(moveY, -this.maxMoveY, this.maxMoveY);
}
if (this.zooming && touches.length === 2) {
const distance = getDistance(touches);
const scale = (this.startScale * distance) / this.startDistance;
this.scale = range(scale, this.minZoom, this.maxZoom);
}
},
onImageTouchEnd(event) {
/* istanbul ignore else */
if (this.moving || this.zooming) {
let stopPropagation = true;
if (
this.moving &&
this.startMoveX === this.moveX &&
this.startMoveY === this.moveY
) {
stopPropagation = false;
}
if (!event.touches.length) {
this.moving = false;
this.zooming = false;
this.startMoveX = 0;
this.startMoveY = 0;
this.startScale = 1;
if (this.scale < 1) {
this.resetScale();
}
}
if (stopPropagation) {
preventDefault(event, true);
}
}
},
onSwipeChange(active) {
this.resetScale();
this.active = active;
this.$emit('change', active);
},
resetScale() {
this.scale = 1;
this.moveX = 0;
this.moveY = 0;
}
},
render(h) {
if (!this.value) {
return;
}
const { active, images } = this;
const Index = this.showIndex && (
<div class={bem('index')}>
{this.slots('index') || `${active + 1}/${images.length}`}
</div>
);
const Images = (
<Swipe
ref="swipe"
loop={this.loop}
indicatorColor="white"
initialSwipe={this.startPosition}
showIndicators={this.showIndicators}
onChange={this.onSwipeChange}
>
{images.map((image, index) => {
const props = {
class: bem('image'),
style: index === active ? this.imageStyle : null,
on: {
touchstart: this.onImageTouchStart,
touchmove: this.onImageTouchMove,
touchend: this.onImageTouchEnd,
touchcancel: this.onImageTouchEnd
}
};
return (
<SwipeItem>
{this.lazyLoad ? (
<img vLazy={image} {...props} />
) : (
<img src={image} {...props} />
)}
</SwipeItem>
);
})}
</Swipe>
);
return (
<transition name="van-fade">
<div
class={[bem(), this.className]}
onTouchstart={this.onWrapperTouchStart}
onTouchMove={preventDefault}
onTouchend={this.onWrapperTouchEnd}
onTouchcancel={this.onWrapperTouchEnd}
>
{Index}
{Images}
</div>
</transition>
);
}
});
+127
View File
@@ -0,0 +1,127 @@
<template>
<demo-section>
<demo-block :title="$t('basicUsage')">
<van-button
type="primary"
@click="showImagePreview"
>
{{ $t('button1') }}
</van-button>
</demo-block>
<demo-block :title="$t('button2')">
<van-button
type="primary"
@click="showImagePreview(1)"
>
{{ $t('button2') }}
</van-button>
</demo-block>
<demo-block :title="$t('button3')">
<van-button
type="primary"
@click="showImagePreview(0, 1000)"
>
{{ $t('button3') }}
</van-button>
</demo-block>
<demo-block :title="$t('componentCall')">
<van-button
type="primary"
@click="componentCall"
>
{{ $t('componentCall') }}
</van-button>
<van-image-preview
v-model="show"
:images="images"
@change="onChange"
>
<template #index>{{ $t('index', index) }}</template>
</van-image-preview>
</demo-block>
</demo-section>
</template>
<script>
import { ImagePreview } from '../..';
const images = [
'https://img.yzcdn.cn/public_files/2017/09/05/3bd347e44233a868c99cf0fe560232be.jpg',
'https://img.yzcdn.cn/public_files/2017/09/05/c0dab461920687911536621b345a0bc9.jpg',
'https://img.yzcdn.cn/public_files/2017/09/05/4e3ea0898b1c2c416eec8c11c5360833.jpg',
'https://img.yzcdn.cn/public_files/2017/09/05/fd08f07665ed67d50e11b32a21ce0682.jpg'
];
export default {
i18n: {
'zh-CN': {
button1: '预览图片',
button2: '指定初始位置',
button3: '异步关闭',
componentCall: '组件调用',
index: index => `${index + 1}`
},
'en-US': {
button1: 'Show Images',
button2: 'Custom Start Position',
button3: 'Async Close',
componentCall: 'Component Call',
index: index => `Page: ${index}`
}
},
data() {
return {
show: false,
images,
index: 0
};
},
methods: {
componentCall() {
this.show = true;
},
onChange(index) {
this.index = index;
},
showImagePreview(position, timer) {
const instance = ImagePreview({
images,
asyncClose: !!timer,
closeOnPopstate: true,
startPosition: typeof position === 'number' ? position : 0
});
if (timer) {
setTimeout(() => {
instance.close();
}, timer);
}
}
}
};
</script>
<style lang="less">
@import "../../style/var";
.demo-image-preview {
background-color: @white;
.van-button {
margin-left: 15px;
}
}
.van-image-preview {
img {
-webkit-user-drag: none;
}
}
</style>
+140
View File
@@ -0,0 +1,140 @@
# ImagePreview
### Install
```js
import { ImagePreview } from 'vant';
Vue.use(ImagePreview);
```
## Usage
### Basic Usage
```javascript
ImagePreview([
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
]);
```
### Custom config
```javascript
ImagePreview({
images: [
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
],
startPosition: 1,
onClose() {
// do something
}
});
```
### Async Close
```javascript
const instance = ImagePreview({
images: [
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
],
asyncClose: true
});
setTimeout(() => {
instance.close();
}, 1000);
```
### Component Call
```html
<van-image-preview
v-model="show"
:images="images"
@change="onChange"
>
<template v-slot:index>Page: { index }</template>
</van-image-preview>
```
```js
export default {
data() {
return {
show: false,
index: 0,
images: [
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
]
};
},
methods: {
onChange(index) {
this.index = index;
}
}
}
```
## API
### Options
| Attribute | Description | Type | Default |
|------|------|------|------|
| images | Images URL list | `Array` | `[]` |
| startPosition | Start position | `Number` | `0` |
| showIndex | Whether to show index | `Boolean` | `true` |
| showIndicators | Whether to show indicators | `Boolean` | `false` |
| loop | Whether to enable loop | `Boolean` | `true` |
| onClose | Triggered when close | `Function` | - |
| onChange | Triggered when current image change | `Function` | - |
| closeOnPopstate | Whether to close when popstate | `Boolean` | `false` |
| asyncClose | Whether to enable async close | `Boolean` | `false` |
| className | Custom className | `String | Array | Object` | - |
| lazyLoad | Whether to enable thumb lazy loadshould register [Lazyload](#/en-US/lazyload) component | `Boolean` | `false` |
| maxZoom | Max zoom | `Number` | `3` |
| minZoom | Min zoom | `Number` | `1/3` |
### Props
| Attribute | Description | Type | Default |
|------|------|------|------|
| images | Images URL list | `Array` | `[]` |
| start-position | Start position | `Number` | `0` |
| show-index | Whether to show index | `Boolean` | `true` |
| show-indicators | Whether to show indicators | `Boolean` | `false` |
| loop | Whether to enable loop | `Boolean` | `true` |
| async-close | Whether to enable async close | `Boolean` | `false` |
| close-on-popstate | Whether to close when popstate | `Boolean` | `false` |
| class-name | Custom className | `String | Array | Object` | - |
| lazy-load | Whether to enable thumb lazy loadshould register [Lazyload](#/en-US/lazyload) component | `Boolean` | `false` |
| max-zoom | Max zoom | `Number` | `3` |
| min-zoom | Min zoom | `Number` | `1/3` |
### Events
| Event | Description | Parameters |
|------|------|------|
| close | Triggered when close | { index, url } |
| change | Triggered when current image change | index: index of current image |
### Slots
| Name | Description |
|------|------|
| index | Custom index |
### onClose Parematers
| Attribute | Description | Type |
|------|------|------|
| url | Url of current image | `Number` |
| index | Index of current image | `String` |
+64
View File
@@ -0,0 +1,64 @@
import Vue from 'vue';
import VueImagePreview from './ImagePreview';
import { isServer } from '../utils';
let instance;
const defaultConfig = {
images: [],
loop: true,
value: true,
minZoom: 1 / 3,
maxZoom: 3,
className: '',
lazyLoad: false,
showIndex: true,
asyncClose: false,
startPosition: 0,
showIndicators: false,
closeOnPopstate: false
};
const initInstance = () => {
instance = new (Vue.extend(VueImagePreview))({
el: document.createElement('div')
});
document.body.appendChild(instance.$el);
instance.$on('change', index => {
if (instance.onChange) {
instance.onChange(index);
}
});
};
const ImagePreview = (images, startPosition = 0) => {
/* istanbul ignore if */
if (isServer) {
return;
}
if (!instance) {
initInstance();
}
const options = Array.isArray(images) ? { images, startPosition } : images;
Object.assign(instance, defaultConfig, options);
instance.$once('input', show => {
instance.value = show;
});
if (options.onClose) {
instance.$once('close', options.onClose);
}
return instance;
};
ImagePreview.install = () => {
Vue.use(VueImagePreview);
};
export default ImagePreview;
+38
View File
@@ -0,0 +1,38 @@
@import '../style/var';
.van-image-preview {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
&__image {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
max-width: 100%;
max-height: 100%;
margin: auto;
}
&__index {
position: absolute;
top: 10px;
left: 50%;
color: @image-preview-index-text-color;
font-size: @image-preview-index-font-size;
letter-spacing: 2px;
transform: translate(-50%, 0);
}
&__overlay {
background-color: @image-preview-overlay-background-color;
}
.van-swipe {
height: 100%;
}
}
@@ -0,0 +1,49 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`index slot 1`] = `
<div class="van-image-preview" name="van-fade">
<div class="van-image-preview__index">Custom Index</div>
<div class="van-swipe">
<div class="van-swipe__track" style="width: 0px; transition-duration: 0ms; transform: translateX(0px);"></div>
</div>
</div>
`;
exports[`lazy-load prop 1`] = `
<div class="van-image-preview" name="van-fade">
<div class="van-image-preview__index">1/3</div>
<div class="van-swipe">
<div class="van-swipe__track" style="width: 0px; transition-duration: 0ms; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img class="van-image-preview__image" style="transition: .3s all;"></div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img class="van-image-preview__image"></div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img class="van-image-preview__image"></div>
</div>
</div>
</div>
`;
exports[`render image 1`] = `
<div class="van-image-preview" name="van-fade">
<div class="van-image-preview__index">1/3</div>
<div class="van-swipe">
<div class="van-swipe__track" style="width: 0px; transition-duration: 500ms; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/1.png" class="van-image-preview__image" style="transition: .3s all;"></div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/2.png" class="van-image-preview__image"></div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/3.png" class="van-image-preview__image"></div>
</div>
</div>
</div>
`;
exports[`zoom 1`] = `
<div class="van-image-preview" name="van-fade">
<div class="van-image-preview__index">1/3</div>
<div class="van-swipe">
<div class="van-swipe__track" style="transition-duration: 500ms; width: 0px; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/1.png" class="van-image-preview__image" style="transform: scale3d(2, 2, 1) translate(0px, NaNpx);"></div>
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/2.png" class="van-image-preview__image"></div>
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/3.png" class="van-image-preview__image"></div>
</div>
</div>
</div>
`;
+168
View File
@@ -0,0 +1,168 @@
import Vue from 'vue';
import ImagePreview from '..';
import ImagePreviewVue from '../ImagePreview';
import { mount, trigger, triggerDrag, transitionStub, later } from '../../../test/utils';
transitionStub();
function triggerZoom(el, x, y) {
trigger(el, 'touchstart', 0, 0, { x, y });
trigger(el, 'touchmove', -x / 4, -y / 4, { x, y });
trigger(el, 'touchmove', -x / 3, -y / 3, { x, y });
trigger(el, 'touchmove', -x / 2, -y / 2, { x, y });
trigger(el, 'touchmove', -x, -y, { x, y });
trigger(el, 'touchend', 0, 0, { touchList: [] });
}
const images = [
'https://img.yzcdn.cn/1.png',
'https://img.yzcdn.cn/2.png',
'https://img.yzcdn.cn/3.png'
];
test('render image', () => {
const wrapper = mount(ImagePreviewVue, {
propsData: { images, value: true }
});
expect(wrapper).toMatchSnapshot();
const swipe = wrapper.find('.van-swipe__track');
triggerDrag(swipe, 500, 0);
expect(wrapper.emitted('input')).toBeFalsy();
triggerDrag(swipe, 0, 0);
expect(wrapper.emitted('input')[0][0]).toBeFalsy();
expect(wrapper.emitted('change')[0][0]).toEqual(2);
});
test('async close', () => {
const wrapper = mount(ImagePreviewVue, {
propsData: {
images,
value: true,
asyncClose: true
}
});
const swipe = wrapper.find('.van-swipe__track');
triggerDrag(swipe, 0, 0);
expect(wrapper.emitted('input')).toBeFalsy();
wrapper.vm.close();
expect(wrapper.emitted('input')[0][0]).toBeFalsy();
});
test('function call', done => {
ImagePreview(images);
ImagePreview(images.slice(0, 1));
Vue.nextTick(() => {
const wrapper = document.querySelector('.van-image-preview');
const swipe = wrapper.querySelector('.van-swipe__track');
triggerDrag(swipe, 0, 0);
expect(wrapper.querySelectorAll('img').length).toEqual(1);
done();
});
});
test('onClose option', async done => {
const onClose = jest.fn();
const instance = ImagePreview({
images,
startPostion: 1,
onClose
});
instance.$emit('input', true);
expect(onClose).toHaveBeenCalledTimes(0);
await later();
const wrapper = document.querySelector('.van-image-preview');
const swipe = wrapper.querySelector('.van-swipe__track');
triggerDrag(swipe, 0, 0);
expect(onClose).toHaveBeenCalledTimes(1);
expect(onClose).toHaveBeenCalledWith({ index: 0, url: 'https://img.yzcdn.cn/1.png' });
done();
});
test('onChange option', async done => {
const instance = ImagePreview({
images,
startPostion: 0,
onChange(index) {
expect(index).toEqual(2);
done();
}
});
const swipe = instance.$el.querySelector('.van-swipe__track');
triggerDrag(swipe, 1000, 0);
});
test('register component', () => {
Vue.use(ImagePreview);
expect(Vue.component(ImagePreviewVue.name)).toBeTruthy();
});
test('zoom', async () => {
const { getBoundingClientRect } = Element.prototype;
Element.prototype.getBoundingClientRect = jest.fn(() => ({ width: 100 }));
const wrapper = mount(ImagePreviewVue, {
propsData: { images, value: true }
});
const image = wrapper.find('img');
triggerZoom(image, 300, 300);
triggerDrag(image, 300, 300);
expect(wrapper).toMatchSnapshot();
Element.prototype.getBoundingClientRect = getBoundingClientRect;
});
test('index slot', () => {
const wrapper = mount({
template: `
<van-image-preview :value="true">
<template v-slot:index>Custom Index</template>
</van-image-preview>
`
});
expect(wrapper).toMatchSnapshot();
});
test('closeOnPopstate', () => {
const wrapper = mount(ImagePreviewVue, {
propsData: {
images,
value: true,
closeOnPopstate: true
}
});
trigger(window, 'popstate');
expect(wrapper.emitted('input')[0][0]).toBeFalsy();
wrapper.setProps({
value: true,
closeOnPopstate: false
});
trigger(window, 'popstate');
expect(wrapper.emitted('input')[1]).toBeFalsy();
});
test('lazy-load prop', () => {
const wrapper = mount(ImagePreviewVue, {
propsData: {
images,
lazyLoad: true
}
});
wrapper.setProps({
value: true
});
expect(wrapper).toMatchSnapshot();
});
+158
View File
@@ -0,0 +1,158 @@
# ImagePreview 图片预览
### 引入
`ImagePreview`和其他组件不同,不是通过HTML结构的方式来使用,而是通过函数调用的方式。使用前需要先引入它。
```js
import { ImagePreview } from 'vant';
Vue.use(ImagePreview);
```
## 代码演示
### 基础用法
直接传入图片数组,即可展示图片预览
```javascript
ImagePreview([
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
]);
```
### 传入配置项
通过传入配置对象,可以指定初始图片的位置、监听关闭事件
```javascript
ImagePreview({
images: [
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
],
startPosition: 1,
onClose() {
// do something
}
});
```
### 异步关闭
通过`asyncClose`属性可以开启异步关闭,开启后异步关闭后,只能通过实例上的 close 方法关闭图片预览
```javascript
const instance = ImagePreview({
images: [
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
],
asyncClose: true
});
setTimeout(() => {
instance.close();
}, 1000);
```
### 组件调用
如果需要在图片预览内嵌入组件或其他自定义内容,可以使用组件调用的方式,调用前需要通过 `Vue.use` 注册组件
```html
<van-image-preview
v-model="show"
:images="images"
@change="onChange"
>
<template v-slot:index>第{ index }页</template>
</van-image-preview>
```
```js
export default {
data() {
return {
show: false,
index: 0,
images: [
'https://img.yzcdn.cn/1.jpg',
'https://img.yzcdn.cn/2.jpg'
]
};
},
methods: {
onChange(index) {
this.index = index;
}
}
}
```
## API
### Options
通过函数调用 `ImagePreview` 时,支持传入以下选项:
| 参数名 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------|
| images | 需要预览的图片 URL 数组 | `Array` | `[]` | 1.1.16 |
| startPosition | 图片预览起始位置索引 | `Number` | `0` | 1.1.16 |
| showIndex | 是否显示页码 | `Boolean` | `true` | 1.3.4 |
| showIndicators | 是否显示轮播指示器 | `Boolean` | `false` | 1.3.10 |
| loop | 是否开启循环播放 | `Boolean` | `true` | 1.4.4 |
| onClose | 关闭时的回调函数 | `Function` | - | 1.1.16 |
| onChange | 切换图片时的回调函数,回调参数为当前索引 | `Function` | - | 2.0.3 |
| asyncClose | 是否开启异步关闭 | `Boolean` | `false` | 1.4.8 |
| closeOnPopstate | 是否在页面回退时自动关闭 | `Boolean` | `false` | 2.0.0 |
| className | 自定义类名 | `String | Array | Object` | - | 1.5.2 |
| lazyLoad | 是否开启图片懒加载,须配合 [Lazyload](#/zh-CN/lazyload) 组件使用 | `Boolean` | `false` | 1.5.3 |
| maxZoom | 手势缩放时,最大缩放比例 | `Number` | `3` | 1.6.14 |
| minZoom | 手势缩放时,最小缩放比例 | `Number` | `1/3` | 1.6.14 |
### Props
通过组件调用 `ImagePreview` 时,支持以下 Props
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------|
| images | 需要预览的图片 URL 数组 | `Array` | `[]` | 1.1.16 |
| start-position | 图片预览起始位置索引 | `Number` | `0` | 1.1.16 |
| show-index | 是否显示页码 | `Boolean` | `true` | 1.3.4 |
| show-indicators | 是否显示轮播指示器 | `Boolean` | `false` | 1.3.10 |
| loop | 是否开启循环播放 | `Boolean` | `true` | 1.4.4 |
| async-close | 是否开启异步关闭 | `Boolean` | `false` | 1.4.8 |
| close-on-popstate | 是否在页面回退时自动关闭 | `Boolean` | `false` |
| class-name | 自定义类名 | `String | Array | Object` | - | 1.5.2 |
| lazy-load | 是否开启图片懒加载,须配合 [Lazyload](#/zh-CN/lazyload) 组件使用 | `Boolean` | `false` | 1.5.3 |
| max-zoom | 手势缩放时,最大缩放比例 | `Number` | `3` | 1.6.14 |
| min-zoom | 手势缩放时,最小缩放比例 | `Number` | `1/3` | 1.6.14 |
### Events
通过组件调用 `ImagePreview` 时,支持以下事件:
| 事件 | 说明 | 回调参数 |
|------|------|------|
| close | 关闭时触发 | { index: 索引, url: 图片链接 } |
| change | 切换当前图片时触发 | index, 当前图片的索引 |
### Slots
通过组件调用 `ImagePreview` 时,支持以下插槽:
| 名称 | 说明 |
|------|------|
| index | 自定义页码内容 |
### onClose 回调参数
| 参数名 | 说明 | 类型 |
|------|------|------|
| url | 当前图片 URL | `String` |
| index | 当前图片的索引值 | `Number` |