1
votes

Afficher une animation de chargement lors d'une fonction vue js

Un simple show and hide sur l'élément de chargement échoue lors de l'exécution de la fonction Vue js.

J'ai une fonction vue js qui va faire certaines choses et mettre à jour les données quand c'est fait. J'essaye de montrer une animation de chargement pendant ce processus. J'ai réduit le processus à une simple boucle aux fins de cette discussion afin d'éliminer tous les autres problèmes (c'est-à-dire ajax, async, etc.).

Mon HTMl pour le bouton ressemble à ceci: p>

var client = new Vue({
    el: '#client',
    data: {
        someData: []
},
methods: {
    DoStuff: function() {

        //Show Loader
        $(".loader").show();

        //Waste 5 seconds
        for (var i = 0; i < 100000000; i++) {
            var x = i;
        }

        //Hide loader
        $(".loader").hide();

        // let me know it's done.
        alert('cool');
    }

Mon code vue js ressemble à ceci:

<button type="button" v-on:click="DoStuff()">Do Stuff</button>

Le chargeur ne s'affiche jamais. Si je commente la commande hide, le chargeur apparaît APRÈS l'alerte. Cela me fait penser qu'une sorte d'opération asynchrone est en cours sous le capot, mais je ne fais pas de trucs asynchrones.


1 commentaires

Quelque chose pour aider à expliquer le problème actuel: le DOM ne sera pas rendu tant que votre fonction n'est pas terminée. Pour en savoir plus, cliquez ici: stackoverflow.com/questions/30188845/...


4 Réponses :


5
votes

Vous n'avez pas besoin d'utiliser jQuery pour définir et masquer des éléments sur la page en fonction d'une condition, en fait, cela va à l'encontre de l'objectif de l'utilisation de VueJS et d'autres frameworks javascript frontaux. devrait ajouter une propriété appelée chargement à votre objet data

var client = new Vue({
    el: '#client',
    data: {
        someData: [],
        loading: false
    },
    methods: {
       doStuff: function() {
          //Show Loader
          this.loading = true;

          //Waste 5 seconds
          setTimeout(() => {
            this.loading = false;
          }, 5000)
       }

   }
}

Ensuite, dans votre fonction doStuff , supprimez les lignes jquery et définissez la propriété de chargement en conséquence

<div v-if="loading">Loading some data</div>

Enfin, à votre avis, ajoutez cette ligne

methods: {
    doStuff: function() {
        //Show Loader
        this.loading = true;

        //Waste 5 seconds
        setTimeout(() => {
           this.loading = false;
        }, 5000)
    }
}

Je terminerai en disant que je pense aussi que votre extrait de code est un peu foiré. la propriété methods doit être à l'intérieur de la définition de l'instance Vue.

data: {
   someData: [],
   loading: false
}


2 commentaires

Merci. Voir ma réponse au perellorodrigo ci-dessous. Cette approche n'est pas évolutive sur de nombreux formulaires et pages.


@ArdAtak Vous ne le faites toujours pas et vous ne devriez pas utiliser jquery. C'est la bonne approche, il vous suffit de définir le chargement dans les composants parents et de le transmettre aux accessoires enfants. Je dis aussi simplement que je pense que vous avez une mauvaise compréhension du mot évolutif



0
votes

Il vaut mieux ne pas mélanger avec JQuery, utilisez simplement l'affichage conditionnel Vue à la place (v-show).

Dans votre chargeur:

var client = new Vue({
    el: '#client',
    data: {
        someData: [],
        loading: false
},
methods: {
    DoStuff: function() {

        this.loading = true;

        //Waste 5 seconds
        for (var i = 0; i < 100000000; i++) {
            var x = i;
        }

        this.loading = false;

        // let me know it's done.
        alert('cool');
    }

Dans votre code Vue:

<div class="loader" v-show="loading"></div>


2 commentaires

Merci. Le problème est que j'essaie d'utiliser UNE animation de chargement global sur la page parent et de la manipuler à partir des commandes globales qui font des appels ajax. Je ne veux donc pas poivrer chaque formulaire et chaque fonction avec des animations de chargement et des éléments de chargement séparés. J'ai essayé de simplifier le problème pour montrer qu'à chaque fois qu'un bouton vue js est cliqué et que la fonction est exécutée, le Show / Hide le plus basique échoue. Bien que, comme je l'ai mentionné, si je commente la commande Masquer, le chargeur apparaît après l'alerte.


OK, si c'est le cas, vous devez utiliser un bus d'événements. En utilisant des événements, vous n'êtes pas limité aux relations enfants-parents. Ainsi, chaque fois que vous faites une demande, vous déclenchez l'événement dans n'importe quel enfant et l'attrapez dans le parent. Lisez cet article, vous serez probablement plus intéressé par la dernière partie de celui-ci: flaviocopes.com / vue-components-communication



1
votes

N'utilisez pas jquery. Vous pouvez le faire avec vuejs.

<div class="loading" v-if="loading">
    Loading....
</div>
<div v-else>
The rest of your website 
</div>

Et votre HTML.

var client = new Vue({
    el: '#client',
    data: {
        someData: [],
        loading: false,
},
methods: {
    DoStuff() {

        //Show Loader
        this.loading = true;

        //Waste 5 seconds

        //Hide loader
        this.loading = true;

        // let me know it's done.
        alert('cool');
    }


0 commentaires

-2
votes

Merci à tous. Je dois me concentrer sur une caractéristique plus importante qui est apparue. Mais je voulais juste partager ce que j'ai brillé. Ce n'est pas une (ou la) réponse finale, mais cela explique le problème et la bonne approche.

Le problème a été correctement identifié par Andrew Lohr comme expliqué plus en détail ici: jQuery hide () and show () pas immédiatement exécuté lorsqu'il est inversé plus tard dans la fonction

La meilleure solution (mais pas seulement) serait d'utiliser un bus d'événements comme mentionné par perellorodrigo ici: https://flaviocopes.com/vue-components-communication/

Je publierai ma solution finale lorsque j'y arriverai.


1 commentaires

l'approche correcte n'utilise pas jquery avec vue.