feat: migrate ImagePreview component

This commit is contained in:
chenjiahan 2020-08-17 10:38:11 +08:00
parent b4e02668cf
commit 3a290ce564
7 changed files with 104 additions and 71 deletions

View File

@ -64,4 +64,5 @@ module.exports = [
'collapse-item', 'collapse-item',
'swipe', 'swipe',
'swipe-item', 'swipe-item',
'image-preview',
]; ];

View File

@ -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>
); );
}, },
}); });

View File

@ -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>

View File

@ -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;

View File

@ -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%;

View File

@ -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

View File

@ -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',