Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having mounted() only run once on a component Vue.js

I have two components that conditionally render with v-if:

<Element v-if="this.mode === 'mode'"/>
<OtherElement v-if="this.mode !== 'mode'"/>

I have load-in animations for both components that I have under mounted(), that I only want to run the first time they are loaded. But with mounted, each time the component is recreated when this.mode changes, the animations trigger again. How can I avoid this?

like image 810
Kevin Avatar asked Feb 22 '19 18:02

Kevin


People also ask

What is mounted () in Vue?

The mounted() hook is the most commonly used lifecycle hook in Vue. Vue calls the mounted() hook when your component is added to the DOM. It is most often used to send an HTTP request to fetch data that the component will then render.

Does V if trigger mounted?

Lifecycle Hooks When Vue renders a component because the v-if expression became truthy, it triggers both the 'created' and 'mounted' hooks. For example, the below code will print both 'Created! ' and 'Mounted!

What is the difference between created and mounted in Vue?

The created() hook is used for fetching data from backend API and setting it to data properties. But in SSR, the mounted hook isn't present and requires the performance of tasks like fetching data in created hook only.

What is created () in Vue JS?

created() and mounted()in Vue.js If the Vue instance is created created () hook allows you to add code to be run. Let's look at the differences. Reactive data can be accessed when the processing of the options is finished and you can also change them if you want.


3 Answers

You could wrap your components within a keep-alive element ..

<keep-alive>
    <Element v-if="this.mode === 'mode'"/>
    <OtherElement v-else />
</keep-alive>
like image 95
Husam Ibrahim Avatar answered Oct 19 '22 19:10

Husam Ibrahim


Using v-if, re-renders components every time the this.mode changes. Vue stores them in virtual DOM, but re-renders them if you use v-if.

If you have access to code for these components, consider using prop for v-show and watching it, in optional combination with emitso you can communicate between parent and child components, and set flag if you need it in child and in parent component if child component loads animation initially, to avoid loading it all over again.

This would be one of the child components:

<template>
    <div v-show="mode === 'themode'">

    </div>
</template>
<script>


    export default {
        props: {
            mode: {
                type: Boolean,
                required: true,
                twoWay: true
            },
        },
        data()  {
            return {
                animationLoaded : false,
            }
        },
        mounted(){



        },
         watch: {
           'mode' : function(){
            if(this.mode === 'mode' && this.animationLoaded === false){
                //load animation and set flag to true, to avoid loading it again. 
                this.animationLoaded = true; 
                this.$root.$emit('component-name:animation-loaded');
            }
          }
        },

...

And putting child in parent component:

  <child-component :mode.sync="mode"></child-component>
like image 2
Nikola Kirincic Avatar answered Oct 19 '22 20:10

Nikola Kirincic


If created() doesn't do the job, you should try to do a simple check in the parent element if this.mode was switched on and off before, save the result as a variable and pass that to the mounted hook and only run the animation if the mode wasn't switched before.

like image 1
Luddens Desir Avatar answered Oct 19 '22 20:10

Luddens Desir