mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-05-22 06:31:45 +08:00
feat: migrate ImagePreview component
This commit is contained in:
parent
b4e02668cf
commit
3a290ce564
@ -64,4 +64,5 @@ module.exports = [
|
|||||||
'collapse-item',
|
'collapse-item',
|
||||||
'swipe',
|
'swipe',
|
||||||
'swipe-item',
|
'swipe-item',
|
||||||
|
'image-preview',
|
||||||
];
|
];
|
||||||
|
@ -3,21 +3,18 @@ import { inBrowser } from '../utils';
|
|||||||
import { bem, createComponent } from './shared';
|
import { bem, createComponent } from './shared';
|
||||||
|
|
||||||
// Mixins
|
// Mixins
|
||||||
import { PopupMixin } from '../mixins/popup';
|
|
||||||
import { TouchMixin } from '../mixins/touch';
|
import { TouchMixin } from '../mixins/touch';
|
||||||
import { BindEventMixin } from '../mixins/bind-event';
|
import { BindEventMixin } from '../mixins/bind-event';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
import Swipe from '../swipe';
|
import Swipe from '../swipe';
|
||||||
|
import Popup from '../popup';
|
||||||
import ImagePreviewItem from './ImagePreviewItem';
|
import ImagePreviewItem from './ImagePreviewItem';
|
||||||
|
|
||||||
export default createComponent({
|
export default createComponent({
|
||||||
mixins: [
|
mixins: [
|
||||||
TouchMixin,
|
TouchMixin,
|
||||||
PopupMixin({
|
|
||||||
skipToggleEvent: true,
|
|
||||||
}),
|
|
||||||
BindEventMixin(function (bind) {
|
BindEventMixin(function (bind) {
|
||||||
bind(window, 'resize', this.resize, true);
|
bind(window, 'resize', this.resize, true);
|
||||||
bind(window, 'orientationchange', this.resize, true);
|
bind(window, 'orientationchange', this.resize, true);
|
||||||
@ -25,6 +22,7 @@ export default createComponent({
|
|||||||
],
|
],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
show: Boolean,
|
||||||
className: null,
|
className: null,
|
||||||
closeable: Boolean,
|
closeable: Boolean,
|
||||||
asyncClose: Boolean,
|
asyncClose: Boolean,
|
||||||
@ -61,10 +59,6 @@ export default createComponent({
|
|||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
overlayClass: {
|
|
||||||
type: String,
|
|
||||||
default: bem('overlay'),
|
|
||||||
},
|
|
||||||
closeIcon: {
|
closeIcon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'clear',
|
default: 'clear',
|
||||||
@ -79,6 +73,8 @@ export default createComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['scale', 'close', 'closed', 'change', 'update:show'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
active: 0,
|
active: 0,
|
||||||
@ -95,7 +91,7 @@ export default createComponent({
|
|||||||
watch: {
|
watch: {
|
||||||
startPosition: 'setActive',
|
startPosition: 'setActive',
|
||||||
|
|
||||||
value(val) {
|
show(val) {
|
||||||
if (val) {
|
if (val) {
|
||||||
this.setActive(+this.startPosition);
|
this.setActive(+this.startPosition);
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@ -120,7 +116,7 @@ export default createComponent({
|
|||||||
|
|
||||||
emitClose() {
|
emitClose() {
|
||||||
if (!this.asyncClose) {
|
if (!this.asyncClose) {
|
||||||
this.$emit('input', false);
|
this.$emit('update:show', false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -139,18 +135,17 @@ export default createComponent({
|
|||||||
if (this.showIndex) {
|
if (this.showIndex) {
|
||||||
return (
|
return (
|
||||||
<div class={bem('index')}>
|
<div class={bem('index')}>
|
||||||
{this.slots('index') ||
|
{this.$slots.index
|
||||||
`${this.active + 1} / ${this.images.length}`}
|
? this.$slots.index()
|
||||||
|
: `${this.active + 1} / ${this.images.length}`}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
genCover() {
|
genCover() {
|
||||||
const cover = this.slots('cover');
|
if (this.$slots.cover) {
|
||||||
|
return <div class={bem('cover')}>{this.$slots.cover()}</div>;
|
||||||
if (cover) {
|
|
||||||
return <div class={bem('cover')}>{cover}</div>;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -170,7 +165,7 @@ export default createComponent({
|
|||||||
{this.images.map((image) => (
|
{this.images.map((image) => (
|
||||||
<ImagePreviewItem
|
<ImagePreviewItem
|
||||||
src={image}
|
src={image}
|
||||||
show={this.value}
|
show={this.show}
|
||||||
active={this.active}
|
active={this.active}
|
||||||
maxZoom={this.maxZoom}
|
maxZoom={this.maxZoom}
|
||||||
minZoom={this.minZoom}
|
minZoom={this.minZoom}
|
||||||
@ -210,19 +205,18 @@ export default createComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.shouldRender) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<transition name="van-fade" onAfterLeave={this.onClosed}>
|
<Popup
|
||||||
<div vShow={this.value} class={[bem(), this.className]}>
|
show={this.show}
|
||||||
|
class={[bem(), this.className]}
|
||||||
|
overlayClass={bem('overlay')}
|
||||||
|
onClosed={this.onClosed}
|
||||||
|
>
|
||||||
{this.genClose()}
|
{this.genClose()}
|
||||||
{this.genImages()}
|
{this.genImages()}
|
||||||
{this.genIndex()}
|
{this.genIndex()}
|
||||||
{this.genCover()}
|
{this.genCover()}
|
||||||
</div>
|
</Popup>
|
||||||
</transition>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -31,6 +31,8 @@ export default {
|
|||||||
windowHeight: Number,
|
windowHeight: Number,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['scale', 'close'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
scale: 1,
|
scale: 1,
|
||||||
@ -250,11 +252,11 @@ export default {
|
|||||||
return (
|
return (
|
||||||
<SwipeItem class={bem('swipe-item')}>
|
<SwipeItem class={bem('swipe-item')}>
|
||||||
<Image
|
<Image
|
||||||
|
v-slots={imageSlots}
|
||||||
src={this.src}
|
src={this.src}
|
||||||
fit="contain"
|
fit="contain"
|
||||||
class={bem('image', { vertical: this.vertical })}
|
class={bem('image', { vertical: this.vertical })}
|
||||||
style={this.imageStyle}
|
style={this.imageStyle}
|
||||||
scopedSlots={imageSlots}
|
|
||||||
onLoad={this.onLoad}
|
onLoad={this.onLoad}
|
||||||
/>
|
/>
|
||||||
</SwipeItem>
|
</SwipeItem>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// import Vue from 'vue';
|
import { createApp, nextTick } from 'vue';
|
||||||
import VueImagePreview from './ImagePreview';
|
import VanImagePreview from './ImagePreview';
|
||||||
import { inBrowser } from '../utils';
|
import { inBrowser } from '../utils';
|
||||||
|
|
||||||
let instance;
|
let instance;
|
||||||
|
|
||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
loop: true,
|
loop: true,
|
||||||
value: true,
|
|
||||||
images: [],
|
images: [],
|
||||||
maxZoom: 3,
|
maxZoom: 3,
|
||||||
minZoom: 1 / 3,
|
minZoom: 1 / 3,
|
||||||
|
onScale: null,
|
||||||
onClose: null,
|
onClose: null,
|
||||||
onChange: null,
|
onChange: null,
|
||||||
className: '',
|
className: '',
|
||||||
@ -25,24 +25,59 @@ const defaultConfig = {
|
|||||||
closeIconPosition: 'top-right',
|
closeIconPosition: 'top-right',
|
||||||
};
|
};
|
||||||
|
|
||||||
const initInstance = () => {
|
function initInstance() {
|
||||||
instance = new (Vue.extend(VueImagePreview))({
|
const root = document.createElement('div');
|
||||||
el: document.createElement('div'),
|
document.body.appendChild(root);
|
||||||
});
|
|
||||||
document.body.appendChild(instance.$el);
|
|
||||||
|
|
||||||
instance.$on('change', (index) => {
|
instance = createApp({
|
||||||
if (instance.onChange) {
|
data() {
|
||||||
instance.onChange(index);
|
return {
|
||||||
}
|
props: {
|
||||||
});
|
show: false,
|
||||||
|
},
|
||||||
instance.$on('scale', (data) => {
|
|
||||||
if (instance.onScale) {
|
|
||||||
instance.onScale(data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close() {
|
||||||
|
this.toggle(false);
|
||||||
|
},
|
||||||
|
toggle(show) {
|
||||||
|
this.props.show = show;
|
||||||
|
},
|
||||||
|
setProps(props) {
|
||||||
|
Object.assign(this.props, props);
|
||||||
|
},
|
||||||
|
onClosed() {
|
||||||
|
this.props.images = [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<VanImagePreview
|
||||||
|
{...{
|
||||||
|
...this.props,
|
||||||
|
onClosed: this.onClosed,
|
||||||
|
'onUpdate:show': this.toggle,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}).mount(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// const initInstance = () => {
|
||||||
|
// instance.$on('change', (index) => {
|
||||||
|
// if (instance.onChange) {
|
||||||
|
// instance.onChange(index);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// instance.$on('scale', (data) => {
|
||||||
|
// if (instance.onScale) {
|
||||||
|
// instance.onScale(data);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
const ImagePreview = (images, startPosition = 0) => {
|
const ImagePreview = (images, startPosition = 0) => {
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
@ -56,28 +91,27 @@ const ImagePreview = (images, startPosition = 0) => {
|
|||||||
|
|
||||||
const options = Array.isArray(images) ? { images, startPosition } : images;
|
const options = Array.isArray(images) ? { images, startPosition } : images;
|
||||||
|
|
||||||
Object.assign(instance, defaultConfig, options);
|
instance.setProps({
|
||||||
|
...defaultConfig,
|
||||||
instance.$once('input', (show) => {
|
...options,
|
||||||
instance.value = show;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
instance.$once('closed', () => {
|
nextTick(() => {
|
||||||
instance.images = [];
|
instance.toggle(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (options.onClose) {
|
// if (options.onClose) {
|
||||||
instance.$off('close');
|
// instance.$off('close');
|
||||||
instance.$once('close', options.onClose);
|
// instance.$once('close', options.onClose);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
ImagePreview.Component = VueImagePreview;
|
ImagePreview.Component = VanImagePreview;
|
||||||
|
|
||||||
ImagePreview.install = () => {
|
ImagePreview.install = (app) => {
|
||||||
Vue.use(VueImagePreview);
|
app.use(VanImagePreview);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ImagePreview;
|
export default ImagePreview;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
background-color: transparent;
|
||||||
|
transform: none;
|
||||||
|
|
||||||
&__swipe {
|
&__swipe {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -26,7 +26,7 @@ export function ChildrenMixin(parent, options = {}) {
|
|||||||
this.bindRelation();
|
this.bindRelation();
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
if (this.parent) {
|
if (this.parent) {
|
||||||
this.parent.children = this.parent.children.filter(
|
this.parent.children = this.parent.children.filter(
|
||||||
(item) => item !== this
|
(item) => item !== this
|
||||||
|
@ -241,10 +241,10 @@ module.exports = {
|
|||||||
path: 'empty',
|
path: 'empty',
|
||||||
title: 'Empty 空状态',
|
title: 'Empty 空状态',
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: 'image-preview',
|
path: 'image-preview',
|
||||||
// title: 'ImagePreview 图片预览',
|
title: 'ImagePreview 图片预览',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'lazyload',
|
// path: 'lazyload',
|
||||||
// title: 'Lazyload 懒加载',
|
// title: 'Lazyload 懒加载',
|
||||||
@ -575,10 +575,10 @@ module.exports = {
|
|||||||
path: 'empty',
|
path: 'empty',
|
||||||
title: 'Empty',
|
title: 'Empty',
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: 'image-preview',
|
path: 'image-preview',
|
||||||
// title: 'ImagePreview',
|
title: 'ImagePreview',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'lazyload',
|
// path: 'lazyload',
|
||||||
// title: 'Lazyload',
|
// title: 'Lazyload',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user