157 lines
4.0 KiB
Vue
157 lines
4.0 KiB
Vue
|
|
<template>
|
|||
|
|
<image
|
|||
|
|
class="img-cache"
|
|||
|
|
:src="resource"
|
|||
|
|
:mode="mode"
|
|||
|
|
:lazy-load="lazyLoad"
|
|||
|
|
:fade-show="fadeShow"
|
|||
|
|
:webp="webp"
|
|||
|
|
:show-menu-by-longpress="showMenuByLongpress"
|
|||
|
|
:style="[style]"
|
|||
|
|
@tap="fnEvent('click', $event)"
|
|||
|
|
@error="fnEvent('error', $event)"
|
|||
|
|
@load="fnEvent('load', $event)"
|
|||
|
|
>
|
|||
|
|
</image>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
// #ifdef APP-PLUS
|
|||
|
|
import download from './download'
|
|||
|
|
import { resolveFile, storage } from './index'
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* ImgCache 图片缓存
|
|||
|
|
* @description APP端图片缓存
|
|||
|
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=2515
|
|||
|
|
* @property {string} src 图片资源地址
|
|||
|
|
* @property {string} mode 图片裁剪、缩放的模式
|
|||
|
|
* @property {boolean} lazyLoad 是否图片懒加载
|
|||
|
|
* @property {boolean} fade-show 图片显示动画效果
|
|||
|
|
* @property {boolean} webp 默认不解析 webP 格式,只支持网络资源
|
|||
|
|
* @property {boolean} show-menu-by-longpress 开启长按图片显示识别小程序码菜单
|
|||
|
|
* @property {string} dir 缓存的文件目录,文件夹开头不能有_
|
|||
|
|
* @property {string} width 宽度,单位任意,如果为数值,则为 rpx 单位
|
|||
|
|
* @property {string} height 高度,单位任意,如果为数值,则为 rpx 单位
|
|||
|
|
* @property {object} custom-style 自定义样式
|
|||
|
|
* @event {Function} click 点击图片
|
|||
|
|
* @event {Function} error 错误发生
|
|||
|
|
* @event {Function} load 图片载入完毕
|
|||
|
|
* @example <img-cache src="https://example.com/image.png"></img-cache>
|
|||
|
|
*/
|
|||
|
|
export default {
|
|||
|
|
name: 'ImgCache',
|
|||
|
|
props: {
|
|||
|
|
src: {
|
|||
|
|
type: String
|
|||
|
|
},
|
|||
|
|
mode: {
|
|||
|
|
type: String,
|
|||
|
|
default: 'scaleToFill'
|
|||
|
|
},
|
|||
|
|
lazyLoad: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: false
|
|||
|
|
},
|
|||
|
|
fadeShow: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: true
|
|||
|
|
},
|
|||
|
|
webp: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: false
|
|||
|
|
},
|
|||
|
|
showMenuByLongpress: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: false
|
|||
|
|
},
|
|||
|
|
dir: {
|
|||
|
|
type: String,
|
|||
|
|
default: 'imgcache'
|
|||
|
|
},
|
|||
|
|
width: {
|
|||
|
|
type: [String, Number]
|
|||
|
|
},
|
|||
|
|
height: {
|
|||
|
|
type: [String, Number]
|
|||
|
|
},
|
|||
|
|
customStyle: {
|
|||
|
|
type: Object,
|
|||
|
|
default: () => ({})
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
resource: ''
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
computed: {
|
|||
|
|
style() {
|
|||
|
|
const style = { willChange: 'transform' }
|
|||
|
|
|
|||
|
|
// 判断传过来的值是否为 undefined null false ''
|
|||
|
|
const isEmpty = val => [undefined, null, false, ''].includes(val)
|
|||
|
|
|
|||
|
|
!isEmpty(this.width) && (style.width = this.addUnit(this.width))
|
|||
|
|
!isEmpty(this.height) && (style.height = this.addUnit(this.height))
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
...style,
|
|||
|
|
...this.customStyle
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
watch: {
|
|||
|
|
src: {
|
|||
|
|
handler: 'init',
|
|||
|
|
immediate: true
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
// 初始化
|
|||
|
|
init() {
|
|||
|
|
// #ifdef APP-PLUS
|
|||
|
|
this.fnCache()
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
// #ifndef APP-PLUS
|
|||
|
|
this.setSrc()
|
|||
|
|
// #endif
|
|||
|
|
},
|
|||
|
|
// 获取缓存
|
|||
|
|
async fnCache() {
|
|||
|
|
const url = this.src // 赋值到新变量,避免下载时 src 更改,从而网络地址和本地地址图片不一致
|
|||
|
|
|
|||
|
|
if (!/^https?:\/\//.test(url)) return this.setSrc() // 判断是否网络地址
|
|||
|
|
|
|||
|
|
const [select] = storage.select({ url }) // 查询缓存是否存在
|
|||
|
|
|
|||
|
|
if (select) {
|
|||
|
|
const path = select.local
|
|||
|
|
if (await resolveFile(path)) return this.setSrc(path) // 判断本地文件是否存在 如果存在则显示本地文件
|
|||
|
|
storage.delete(select) // 如果本地文件不存在则删除缓存数据
|
|||
|
|
}
|
|||
|
|
this.setSrc()
|
|||
|
|
|
|||
|
|
const local = await download(url, this.dir) // 下载文件
|
|||
|
|
if (local) storage.insert({ url, local }) // 缓存数据
|
|||
|
|
},
|
|||
|
|
// 设置图片资源地址
|
|||
|
|
setSrc(src) {
|
|||
|
|
this.resource = src || this.src
|
|||
|
|
console.log(src)
|
|||
|
|
},
|
|||
|
|
// 添加单位,如果为数值则为rpx单位,否则直接返回
|
|||
|
|
addUnit(value) {
|
|||
|
|
value = String(value)
|
|||
|
|
return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value) ? `${value}rpx` : value
|
|||
|
|
},
|
|||
|
|
// 发送事件
|
|||
|
|
fnEvent(emit, event) {
|
|||
|
|
this.$emit(emit, event)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|