Using Masonry.JS and Vue.JS Using Masonry.JS and Vue.JS vue.js vue.js

Using Masonry.JS and Vue.JS


I guess the vue-way of doing this is by using refs. Just assign a ref property to your html element inside the template and access it using the vm.$ref instance property inside the mounted callback.

A sample code may look like this:

<template>  <div class="grid" ref="grid">    <div class="grid-item"></div>    <div class="grid-item"></div>    <div class="grid-item"></div>  </div></template><script>  import Masonry from "masonry"; // or maybe use global scoped variable here  export default {    mounted: function(){      let $masonry = new Masonry(this.$refs.grid, {        // masonry options go in here       // see https://masonry.desandro.com/#initialize-with-vanilla-javascript      });    }  }</script>


In Vue2, there is no such thing as a ready lifecycle hook. Instead, the mounted lifecycle hook is triggered once the instance is "ready" in the way you think of.

Reference: https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram


As I saw it, most mv* frameworks like vue keep DOM elements (view) in sync with js (model), in the other hand, frameworks like masonry just need valid DOM to work.So, the tricky part is to tell one to another when DOM has changed.

So the first change is when vue finished to render all DOM, as mentioned in other answers, we are notified on mounted lifecycle hook, here is where we can initialize masonry

mounted() {    let grid = document.querySelector('.grid');    this.msnry = new Masonry(grid, {        columnWidth: 25    });},

In any other change to our view need also update masonry as well, if you change items size use layout() method, if you add or remove items use reloadItems() method

    methods: {        toggle(item) {            item.isGigante = !item.isGigante;            Vue.nextTick(() => {                // DOM updated                this.msnry.layout();            });        },        add() {            this.items.push({                isGigante: false,                size: '' + widthClasses[Math.floor(Math.random() * widthClasses.length)] + ' ' + heightClasses[Math.floor(Math.random() * heightClasses.length)]            });            Vue.nextTick(() => {                // DOM updated                this.msnry.reloadItems();                this.msnry.layout();            });        }    }

Please note that those methods are called after vue has completed DOM update using Vue.nextTick function.Here is a working fiddle.