提交 997964b5 编写于 作者: chenli_1989's avatar chenli_1989

fix: 修复 image 组件 contentPath 字段默认为空导致 img 请求空问题

上级 be1b23b8
<template>
<uni-image v-on="$listeners">
<div
ref="content"
:style="style"
/>
<img :src="contentPath">
<v-uni-resize-sensor
v-if="mode === 'widthFix' || mode === 'heightFix'"
ref="sensor"
@resize="_fixSize()"
/>
</uni-image>
</template>
<script>
function fixNumber (number) {
// fix: 解决 Chrome 浏览器上某些情况下导致 1px 缝隙的问题
if (typeof navigator && navigator.vendor === 'Google Inc.' && number > 10) {
number = Math.round(number / 2) * 2
}
return number
}
export default {
name: 'Image',
props: {
src: {
type: String,
default: ''
},
mode: {
type: String,
default: 'scaleToFill'
},
// TODO 懒加载
lazyLoad: {
type: [Boolean, String],
default: false
}
},
data () {
return {
originalWidth: 0,
originalHeight: 0,
originalStyle: { width: '', height: '' },
contentPath: ''
}
},
computed: {
ratio () {
return this.originalWidth && this.originalHeight ? this.originalWidth / this.originalHeight : 0
},
style () {
let size = 'auto'
let position = ''
const repeat = 'no-repeat'
switch (this.mode) {
case 'aspectFit':
size = 'contain'
position = 'center center'
break
case 'aspectFill':
size = 'cover'
position = 'center center'
break
case 'widthFix':
case 'heightFix':
size = '100% 100%'
break
case 'top':
position = 'center top'
break
case 'bottom':
position = 'center bottom'
break
case 'center':
position = 'center center'
break
case 'left':
position = 'left center'
break
case 'right':
position = 'right center'
break
case 'top left':
position = 'left top'
break
case 'top right':
position = 'right top'
break
case 'bottom left':
position = 'left bottom'
break
case 'bottom right':
position = 'right bottom'
break
default:
size = '100% 100%'
position = '0% 0%'
break
}
return {
'background-image': this.contentPath ? `url("${this.contentPath}")` : 'none',
'background-position': position,
'background-size': size,
'background-repeat': repeat
}
}
},
watch: {
src (newValue, oldValue) {
this._loadImage()
},
mode (newValue, oldValue) {
if (oldValue === 'widthFix' || oldValue === 'heightFix') {
this._resetSize()
}
if (newValue === 'widthFix' || newValue === 'heightFix') {
this._fixSize()
}
}
},
mounted () {
this.originalStyle.width = this.$el.style.width || ''
this.originalStyle.height = this.$el.style.height || ''
this._loadImage()
},
beforeDestroy () {
this._clearImage()
},
methods: {
_fixSize () {
if (this.ratio) {
const $el = this.$el
const rect = $el.getBoundingClientRect()
if (this.mode === 'widthFix') {
const width = rect.width
if (width) {
$el.style.height = fixNumber(width / this.ratio) + 'px'
}
} else if (this.mode === 'heightFix') {
const height = rect.height
if (height) {
$el.style.width = fixNumber(height * this.ratio) + 'px'
}
}
}
},
_resetSize () {
this.$el.style.width = this.originalStyle.width
this.$el.style.height = this.originalStyle.height
},
_resetData () {
this.originalWidth = 0
this.originalHeight = 0
this.contentPath = ''
},
_loadImage () {
const realImagePath = this.$getRealPath(this.src)
if (realImagePath) {
const img = this._img = this._img || new Image()
img.onload = $event => {
this._img = null
this.originalWidth = img.width
this.originalHeight = img.height
this._fixSize()
this.contentPath = realImagePath
this.$trigger('load', $event, {
width: img.width,
height: img.height
})
}
img.onerror = $event => {
this._img = null
this._resetData()
// 与微信小程序保持一致,保留之前样式
// this._resetSize()
this.$trigger('error', $event, {
errMsg: `GET ${this.src} 404 (Not Found)`
})
}
img.src = realImagePath
} else {
this._clearImage()
// 与微信小程序保持一致,保留之前样式
// this._resetData()
this._resetSize()
}
},
_clearImage () {
const img = this._img
if (img) {
img.onload = null
img.onerror = null
this._img = null
}
}
}
}
</script>
<style>
uni-image {
width: 320px;
height: 240px;
display: inline-block;
overflow: hidden;
position: relative;
}
uni-image[hidden] {
display: none;
}
uni-image > div {
width: 100%;
height: 100%;
}
uni-image > img {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
uni-image > .uni-image-will-change {
will-change: transform;
}
</style>
<template>
<uni-image v-on="$listeners">
<div
ref="content"
:style="style"
/>
<img
v-if="contentPath"
:src="contentPath"
>
<v-uni-resize-sensor
v-if="mode === 'widthFix' || mode === 'heightFix'"
ref="sensor"
@resize="_fixSize()"
/>
</uni-image>
</template>
<script>
function fixNumber (number) {
// fix: 解决 Chrome 浏览器上某些情况下导致 1px 缝隙的问题
if (typeof navigator && navigator.vendor === 'Google Inc.' && number > 10) {
number = Math.round(number / 2) * 2
}
return number
}
export default {
name: 'Image',
props: {
src: {
type: String,
default: ''
},
mode: {
type: String,
default: 'scaleToFill'
},
// TODO 懒加载
lazyLoad: {
type: [Boolean, String],
default: false
}
},
data () {
return {
originalWidth: 0,
originalHeight: 0,
originalStyle: { width: '', height: '' },
contentPath: ''
}
},
computed: {
ratio () {
return this.originalWidth && this.originalHeight ? this.originalWidth / this.originalHeight : 0
},
style () {
let size = 'auto'
let position = ''
const repeat = 'no-repeat'
switch (this.mode) {
case 'aspectFit':
size = 'contain'
position = 'center center'
break
case 'aspectFill':
size = 'cover'
position = 'center center'
break
case 'widthFix':
case 'heightFix':
size = '100% 100%'
break
case 'top':
position = 'center top'
break
case 'bottom':
position = 'center bottom'
break
case 'center':
position = 'center center'
break
case 'left':
position = 'left center'
break
case 'right':
position = 'right center'
break
case 'top left':
position = 'left top'
break
case 'top right':
position = 'right top'
break
case 'bottom left':
position = 'left bottom'
break
case 'bottom right':
position = 'right bottom'
break
default:
size = '100% 100%'
position = '0% 0%'
break
}
return {
'background-image': this.contentPath ? `url("${this.contentPath}")` : 'none',
'background-position': position,
'background-size': size,
'background-repeat': repeat
}
}
},
watch: {
src (newValue, oldValue) {
this._loadImage()
},
mode (newValue, oldValue) {
if (oldValue === 'widthFix' || oldValue === 'heightFix') {
this._resetSize()
}
if (newValue === 'widthFix' || newValue === 'heightFix') {
this._fixSize()
}
}
},
mounted () {
this.originalStyle.width = this.$el.style.width || ''
this.originalStyle.height = this.$el.style.height || ''
this._loadImage()
},
beforeDestroy () {
this._clearImage()
},
methods: {
_fixSize () {
if (this.ratio) {
const $el = this.$el
const rect = $el.getBoundingClientRect()
if (this.mode === 'widthFix') {
const width = rect.width
if (width) {
$el.style.height = fixNumber(width / this.ratio) + 'px'
}
} else if (this.mode === 'heightFix') {
const height = rect.height
if (height) {
$el.style.width = fixNumber(height * this.ratio) + 'px'
}
}
}
},
_resetSize () {
this.$el.style.width = this.originalStyle.width
this.$el.style.height = this.originalStyle.height
},
_resetData () {
this.originalWidth = 0
this.originalHeight = 0
this.contentPath = ''
},
_loadImage () {
const realImagePath = this.$getRealPath(this.src)
if (realImagePath) {
const img = this._img = this._img || new Image()
img.onload = $event => {
this._img = null
this.originalWidth = img.width
this.originalHeight = img.height
this._fixSize()
this.contentPath = realImagePath
this.$trigger('load', $event, {
width: img.width,
height: img.height
})
}
img.onerror = $event => {
this._img = null
this._resetData()
// 与微信小程序保持一致,保留之前样式
// this._resetSize()
this.$trigger('error', $event, {
errMsg: `GET ${this.src} 404 (Not Found)`
})
}
img.src = realImagePath
} else {
this._clearImage()
// 与微信小程序保持一致,保留之前样式
// this._resetData()
this._resetSize()
}
},
_clearImage () {
const img = this._img
if (img) {
img.onload = null
img.onerror = null
this._img = null
}
}
}
}
</script>
<style>
uni-image {
width: 320px;
height: 240px;
display: inline-block;
overflow: hidden;
position: relative;
}
uni-image[hidden] {
display: none;
}
uni-image > div {
width: 100%;
height: 100%;
}
uni-image > img {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
uni-image > .uni-image-will-change {
will-change: transform;
}
</style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册