mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[new feature] Image: add loading slot
This commit is contained in:
parent
1321ba6902
commit
d7b69d2fe4
@ -19,6 +19,7 @@
|
||||
>
|
||||
<van-image
|
||||
:fit="fit"
|
||||
width="100%"
|
||||
height="27vw"
|
||||
:src="image"
|
||||
/>
|
||||
@ -26,6 +27,33 @@
|
||||
</van-col>
|
||||
</van-row>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('loading')">
|
||||
<van-row gutter="20">
|
||||
<van-col span="8">
|
||||
<van-image
|
||||
width="100%"
|
||||
height="27vw"
|
||||
/>
|
||||
<div class="text">{{ $t('defaultTip') }}</div>
|
||||
</van-col>
|
||||
|
||||
<van-col span="8">
|
||||
<van-image
|
||||
width="100%"
|
||||
height="27vw"
|
||||
>
|
||||
<template v-slot:loading>
|
||||
<van-loading
|
||||
type="spinner"
|
||||
size="20"
|
||||
/>
|
||||
</template>
|
||||
</van-image>
|
||||
<div class="text">{{ $t('customTip') }}</div>
|
||||
</van-col>
|
||||
</van-row>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
</template>
|
||||
|
||||
@ -33,10 +61,18 @@
|
||||
export default {
|
||||
i18n: {
|
||||
'zh-CN': {
|
||||
fitMode: '缩放模式'
|
||||
fitMode: '填充模式',
|
||||
loading: '加载中提示',
|
||||
error: '加载失败提示',
|
||||
defaultTip: '默认提示',
|
||||
customTip: '自定义提示'
|
||||
},
|
||||
'en-US': {
|
||||
fitMode: 'Fit Mode'
|
||||
fitMode: 'Fit Mode',
|
||||
loading: 'Loading',
|
||||
error: 'Error',
|
||||
defaultTip: 'Default Tip',
|
||||
customTip: 'Custom Tip'
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -78,3 +78,9 @@ Vue.use(Lazyload);
|
||||
| click | Triggered when click image | event: Event |
|
||||
| load | Triggered when image loaded | - |
|
||||
| error | Triggered when image load failed | - |
|
||||
|
||||
### Slots
|
||||
|
||||
| Name | Description |
|
||||
|------|------|
|
||||
| loading | Custom loading placeholder |
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { use, isDef, suffixPx } from '../utils';
|
||||
import Icon from '../icon';
|
||||
|
||||
const [sfc, bem] = use('image');
|
||||
|
||||
@ -19,6 +20,13 @@ export default sfc({
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
src() {
|
||||
this.loading = true;
|
||||
this.error = false;
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
style() {
|
||||
const style = {};
|
||||
@ -48,33 +56,46 @@ export default sfc({
|
||||
|
||||
onClick(event) {
|
||||
this.$emit('click', event);
|
||||
},
|
||||
|
||||
renderContent() {
|
||||
if (this.loading) {
|
||||
return (
|
||||
<div class={bem('loading')}>
|
||||
{this.slots('loading') || <Icon name="photo-o" size="20" />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
renderImage() {
|
||||
const imgData = {
|
||||
class: bem('img'),
|
||||
attrs: {
|
||||
alt: this.alt
|
||||
},
|
||||
style: {
|
||||
objectFit: this.fit
|
||||
},
|
||||
on: {
|
||||
load: this.onLoad,
|
||||
error: this.onError
|
||||
}
|
||||
};
|
||||
|
||||
if (this.lazyLoad) {
|
||||
return <img vLazy={this.src} {...imgData} />;
|
||||
}
|
||||
|
||||
return <img src={this.src} {...imgData} />;
|
||||
}
|
||||
},
|
||||
|
||||
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 ? (
|
||||
<img vLazy={this.src} {...imgData} />
|
||||
) : (
|
||||
<img src={this.src} {...imgData} />
|
||||
);
|
||||
|
||||
return (
|
||||
<div class={bem()} style={this.style} onClick={this.onClick}>
|
||||
{Image}
|
||||
{this.renderImage()}
|
||||
{this.renderContent()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,26 @@
|
||||
@import '../style/var';
|
||||
|
||||
.van-image {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
&__img {
|
||||
&__img,
|
||||
&__error,
|
||||
&__loading {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&__error,
|
||||
&__loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: @gray-dark;
|
||||
background-color: @background-color;
|
||||
}
|
||||
}
|
||||
|
@ -4,32 +4,69 @@ exports[`renders demo correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<div class="van-row">
|
||||
<div class="van-image" style="width: 100px; height: 100px;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img"></div>
|
||||
<div class="van-image" style="width: 100px; height: 100px;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-row" style="margin-left: -10px; margin-right: -10px;">
|
||||
<div class="van-col van-col--8" style="padding-left: 10px; padding-right: 10px;">
|
||||
<div class="van-image" style="height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: contain;"></div>
|
||||
<div class="van-image" style="width: 100%; height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: contain;">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
<div class="text">contain</div>
|
||||
</div>
|
||||
<div class="van-col van-col--8" style="padding-left: 10px; padding-right: 10px;">
|
||||
<div class="van-image" style="height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: cover;"></div>
|
||||
<div class="van-image" style="width: 100%; height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: cover;">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
<div class="text">cover</div>
|
||||
</div>
|
||||
<div class="van-col van-col--8" style="padding-left: 10px; padding-right: 10px;">
|
||||
<div class="van-image" style="height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: fill;"></div>
|
||||
<div class="van-image" style="width: 100%; height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: fill;">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
<div class="text">fill</div>
|
||||
</div>
|
||||
<div class="van-col van-col--8" style="padding-left: 10px; padding-right: 10px;">
|
||||
<div class="van-image" style="height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: none;"></div>
|
||||
<div class="van-image" style="width: 100%; height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: none;">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
<div class="text">none</div>
|
||||
</div>
|
||||
<div class="van-col van-col--8" style="padding-left: 10px; padding-right: 10px;">
|
||||
<div class="van-image" style="height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: scale-down;"></div>
|
||||
<div class="van-image" style="width: 100%; height: 27vw;"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img" style="object-fit: scale-down;">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
<div class="text">scale-down</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-row" style="margin-left: -10px; margin-right: -10px;">
|
||||
<div class="van-col van-col--8" style="padding-left: 10px; padding-right: 10px;">
|
||||
<div class="van-image" style="width: 100%; height: 27vw;"><img class="van-image__img">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
<div class="text">默认提示</div>
|
||||
</div>
|
||||
<div class="van-col van-col--8" style="padding-left: 10px; padding-right: 10px;">
|
||||
<div class="van-image" style="width: 100%; height: 27vw;"><img class="van-image__img">
|
||||
<div class="van-image__loading">
|
||||
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201); width: 20px; height: 20px;"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text">自定义提示</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`lazy load 1`] = `<div class="van-image"><img class="van-image__img"></div>`;
|
||||
exports[`lazy load 1`] = `
|
||||
<div class="van-image"><img class="van-image__img">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`load event 1`] = `<div class="van-image"><img src="https://img.yzcdn.cn/vant/cat.jpeg" class="van-image__img"></div>`;
|
||||
|
||||
exports[`load event 2`] = `
|
||||
<div class="van-image"><img src="" class="van-image__img">
|
||||
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 20px;">
|
||||
<!----></i></div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -19,6 +19,10 @@ test('load event', () => {
|
||||
wrapper.find('img').trigger('load');
|
||||
|
||||
expect(wrapper.emitted('load')[0][0]).toBeTruthy();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
wrapper.setProps({ src: '' });
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('error event', () => {
|
||||
|
@ -20,7 +20,7 @@ Vue.use(Image);
|
||||
/>
|
||||
```
|
||||
|
||||
### 缩放模式
|
||||
### 填充模式
|
||||
|
||||
```html
|
||||
<van-image
|
||||
@ -48,6 +48,18 @@ import { Lazyload } from 'vant';
|
||||
Vue.use(Lazyload);
|
||||
```
|
||||
|
||||
### 加载中提示
|
||||
|
||||
`Image`组件默认提供了图片加载中的提示,可以通过插槽自定义加载中提示
|
||||
|
||||
```html
|
||||
<van-image src="https://img.yzcdn.cn/vant/cat.jpeg">
|
||||
<template v-slot:loading>
|
||||
<van-loading type="spinner" size="20" />
|
||||
</template>
|
||||
</van-image>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
@ -55,13 +67,13 @@ Vue.use(Lazyload);
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
|------|------|------|------|------|
|
||||
| src | 图片链接 | `String` | - | - |
|
||||
| fit | 图片裁剪、缩放的模式 | `String` | `fill` | - |
|
||||
| fit | 图片填充模式 | `String` | `fill` | - |
|
||||
| alt | 替代文本 | `String` | - | - |
|
||||
| width | 宽度,默认单位为 px | `String | Number` | - | - |
|
||||
| height | 高度,默认单位为 px | `String | Number` | - | - |
|
||||
| lazy-load | 是否开启图片懒加载,须配合 [Lazyload](#/zh-CN/lazyload) 组件使用 | `Boolean` | `false` | - |
|
||||
|
||||
### fit 可选值
|
||||
### 图片填充模式
|
||||
|
||||
| 名称 | 含义 |
|
||||
|------|------|
|
||||
@ -78,3 +90,9 @@ Vue.use(Lazyload);
|
||||
| click | 点击图片时触发 | event: Event |
|
||||
| load | 图片加载完毕时触发 | - |
|
||||
| error | 图片加载失败时触发 | - |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
||||
| loading | 自定义加载状态显示内容 |
|
||||
|
Loading…
x
Reference in New Issue
Block a user