故障:在安卓qq浏览器中,v-lazy-image始终无法显示。
原因分析:
经调试,发现qq浏览器中IntersectionObserver缺少一个isIntersecting字段,而v-lazy-image插件是根据isIntersecting来显示图片的,故只能借助intersectionRatio判断。
另外还有一点差别就是如果v-lazy-image组件初始宽高为0的话,会导致intersectionRatio始终为0。
解决方案:
基于v-lazy-image源码修改自定义一个vue插件模块,代码见文末。
v-lazy-image使用的时候设置 src-placeholder ,保证v-lazy-image有个初始大小,这里我随便制作了一个 1x1 的空白图片,示例代码如下
main.js 修改
import { VLazyImagePlugin } from './plugins/VLazyImage'// polyfillrequire('intersection-observer')Vue.use(VLazyImagePlugin)
组件:
修改后的插件源码:plugins/VLazyImage
const VLazyImageComponent = { props: { src: { type: String, required: true }, srcPlaceholder: { type: String, default: '' }, srcset: { type: String }, intersectionOptions: { type: Object, default: () => ({}) }, usePicture: { type: Boolean, default: false } }, inheritAttrs: false, data: () => ({ observer: null, intersected: false, loaded: false }), computed: { srcImage () { return this.intersected ? this.src : this.srcPlaceholder }, srcsetImage () { return this.intersected && this.srcset ? this.srcset : false } }, methods: { load () { if (this.$el.getAttribute('src') !== this.srcPlaceholder) { this.loaded = true this.$emit('load') } } }, render (h) { let img = h('img', { attrs: { src: this.srcImage, srcset: this.srcsetImage }, domProps: this.$attrs, class: { 'v-lazy-image': true, 'v-lazy-image-loaded': this.loaded }, on: { load: this.load } }) if (this.usePicture) { return h('picture', { on: { load: this.load } }, this.intersected ? [ this.$slots.default, img ] : []) } else { return img } }, mounted () { if ('IntersectionObserver' in window) { this.observer = new IntersectionObserver(entries => { const image = entries[0] if (image.isIntersecting || image.intersectionRatio) { this.intersected = true this.observer.disconnect() this.$emit('intersect') } }, this.intersectionOptions) this.observer.observe(this.$el) } else { console.error( "v-lazy-image: this browser doesn't support IntersectionObserver. Please use this polyfill to make it work https://github.com/w3c/IntersectionObserver/tree/master/polyfill." ) } }, destroyed () { this.observer.disconnect() }}export default VLazyImageComponentexport const VLazyImagePlugin = { install: (Vue, opts) => { Vue.component('VLazyImage', VLazyImageComponent) }}