Problem: in Android qq browser, v-lazy-image cannot be displayed all the time.
Cause analysis:
After debugging, it is found that the IntersectionObserver in the qq browser lacks an isIntersecting field, while the v-lazy-image plug-in displays pictures according to isIntersecting, so it can only be judged by using intersectionRatio.
Another difference is that if the initial width and height of the v-lazy-image component is 0, the intersectionRatio will always be 0.
Solution:
Modify and customize a vue plug-in module based on the v-lazy-image source code. See the end of the article for the code.
When v-lazy-image is used, set SRC placeholder to ensure that v-lazy-image has an initial size. Here I randomly make a 1x1 blank image. The example code is as follows
Modify main.js
import { VLazyImagePlugin } from './plugins/VLazyImage' // polyfill require('intersection-observer') Vue.use(VLazyImagePlugin)
Components:
<template> <div> <v-lazy-image :src="product_image" :src-placeholder="lazyPlaceholder"/> <v-lazy-image :src="product_image" :src-placeholder="lazyPlaceholder"/> <v-lazy-image :src="product_image" :src-placeholder="lazyPlaceholder"/> </div> </template> <script> export default { data () { product_image: 'http://img.alicdn.com/imgextra/i1/3990548613/O1CN01VxNcOn2DUnnBu8jIW_!!0-item_pic.jpg', lazyPlaceholder: require('./lazy-placeholder.png') }, mounted () { // ... } } </script>
Source code of the modified plug-in: 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 VLazyImageComponent export const VLazyImagePlugin = { install: (Vue, opts) => { Vue.component('VLazyImage', VLazyImageComponent) } }