0

I am trying to use jQuery Lazy Loading in my Laravel/Vue project but I am struggling to get an image to appear in my Vue component. I have the following img block which I thought would work:

<img v-if="vehicle.photo_path != null" :data-original="'/storage/vehicles/' + vehicle.photo_path" class="lazy" height="180" width="150"/>

I did find this other question on here - Static image src in Vue.js template - however when I try that method I get this: Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead.

So I switched back to the v-bind method but all I am getting is a white box with a grey border - no image. If I v-bind on the src attribute however I can see the image correctly.

I know I have implemented the Lazy Loading plugin correctly as I can successfully call it elsewhere on my site (such as on a blade view), but I'm not sure where I am going wrong. Thank you.

Redback87
  • 47
  • 2
  • 7
  • Chances are the `data-original` is not set by Vue at the time you call `$(img.lazy).lazyload()`. Does the markup for the `` look correct when you inspect it? – Roy J Aug 16 '17 at 14:44
  • Ah that could be a possibility. The mark up itself looks correct, and if I change `data-original` to `src` in the inspector the image shows up so I know the link is right. I am calling `$("img.lazy").lazyload()` at the end of the body of my template view, I'll try moving it around and see if that makes a difference. – Redback87 Aug 16 '17 at 15:05

2 Answers2

0

Try moving the call to $("img.lazy").lazyload() into the mounted() method on your Vue instance. I just had a similar issue with Vue and jQuery Lazyload and that solved it for me. For example:

var app = new Vue({
    el: ...
    data() ...
    computed: ... 
    methods: ...
    mounted() {
        $("img.lazy").lazyload()
    }
})
Clayton
  • 1,967
  • 4
  • 18
  • 26
0

I found many modules on the internet, but I like to avoid modules when I can. So I came up with something else, I don't know if it's the best, but it works and I didn't see any performances loss, I lazy load all the images when the page loads. You may prefer on scroll if you have lots of them, but I guess you'll figure this out if my answer fits your needs.

You'll need vueX for this, but I'll avoid the set up as this is not replying to your question.

If, like me, you have some kind of Index.vue component which main usage is to initiate all the child components (I use to do that for vue-router for instance), place a mounted() function in it :

mounted(){
    const ctx = this;

    // You could use this method, but if you reload the page, the cache of the browser won't allow your JS to trigger .onload method, so better use what's after.
    /*window.onload = function(){
        console.log('page loaded, can load images');
        ctx.$store.dispatch('setPageLoaded', true);
    }*/

    let interval = setInterval(function() {
        if(document.readyState === 'complete') {
            clearInterval(interval);
            ctx.$store.dispatch('setPageLoaded', true);
        }
    }, 100);
}

=> On the page load, I just set a page_load variable in the store to true.

Then, in any component you'd like to lazy load the image, just use 2 computeds (I used a mixin that I include in my components so I avoid repeating some code) :

computed: {
    page_loaded(){
        return this.$store.getters.getPageLoaded;
    },
    image(){
        if(this.page_loaded){
            console.log('starting loading image');

            if(this.product.picture){
                return resizedPicture(this.product.picture, this.width, this.height);
            }else if(this.product.hasOwnProperty('additional_pictures') && this.product.additional_pictures.length){
                return resizedPicture(this.product.additional_pictures[0], this.width, this.height);
            }

            return '';
        }
    }
}

page_loaded() goal is to return the store page_loaded variable I talk about.

image() goal is to actually load the image.

I used that for inline CSS background-image property, so my HTML looks like this :

<span v-if="page_loaded" class="image" :style="'background-image:url('+image+')'" :width="1200" :height="900"></span>

I hope it'll help, but as I said, feel free guys to tell me if it's not optimized.

ZyDucksLover
  • 467
  • 1
  • 7
  • 15