VueJS ne peut pas mettre à jour le composant
P粉517475670
P粉517475670 2024-03-26 20:00:55
0
1
390

J'ai ce Vue 1 composant qui obtient un objet comme accessoire qui doit être rempli par l'utilisateur.

L'objet a la structure suivante :

{
    property1: ...,
    property2: ...,
    inputs: {
        2130: { value: ..., comment: ... },
        2131: { ... },
        ...,
    }

}

Le composant est un simple modal avec un formulaire contenant toutes les entrées nécessaires. Je souhaite vérifier du contenu, effectuer des calculs et modifier les styles de cellule en fonction des entrées de l'utilisateur.

Lorsque le modal se charge, je construis la page, en définissant le modèle pour ces entrées en utilisant leurs identifiants :

v-model="object.inputs[subgroup[1].dx.mob.id].comment"

(Remarque : subgroup[1]是包含表结构“定义”的另一个对象的一部分,通过执行 inputs[subgroup[1].dx.mob.id] J'attends les champs du tableau lié aux entrées correspondantes de l'objet)

Le problème est que peu importe ce que j'essaye, la page ne s'affiche pas à nouveau. <input> Le champ ne contient même pas la valeur, il disparaît dès que je clique dessus.

Ce qui est encore plus étrange, c'est que les valeurs sont réellement définies, mais la seule façon d'obtenir le rendu du composant et de faire toutes les bonnes vérifications et styles dont j'ai besoin est de fermer et de rouvrir le modal ou de le définir sur le parent de la table v-if.

Ce ne sont évidemment pas des options réalisables

  • J'ai besoin que la page soit responsive
  • Recréer le composant (à chaque changement d'entrée) prend trop de temps

Voici ce que j'ai essayé :

  • Construisez dynamiquement un observateur pour chaque entrée
    • Mais vm.$watch l'objet est introuvable pour une raison quelconque.
...forEach((input, index)=>{
    vm.$watch(`object.inputs[${index}].comment`, function(){
            this.$forceUpdate();
        })
}
  • Renvoyer l'entrée dans la propriété calculée et observer

    • Mais la page ne peut pas détecter les changements
  • Démarrer manuellement sur les événements @change et @input this.$forceUpdate()

    • Mais $forceUpdate n'est pas une fonction
  • Déclarez un compteur dans data et incrémentez-le sur les événements @change et @input.

    • Mais la page n'est toujours pas mise à jour.
  • Mettez v-if sur des objets invisibles

    • Mais seul cet objet est restitué
  • Utilisez l'attribut data pour modifier l'attribut :key du composant

    • Mais rien ne s'est passé

Comme prévu, la seule façon de procéder est de détruire et de recréer le composant.

Quelqu'un a-t-il une solution ?

La vilaine solution : Après quelques tentatives infructueuses, j'ai trouvé quelque chose qui fonctionne, même de manière incorrecte. tout réel Les réponses sont toujours les bienvenues.

Essentiellement, j'ai réussi à forcer le rendu du composant :

  • Déclarez une nouvelle variable dans data, je l'ai nommée key (dans mon cas c'est un nombre, mais tout fera l'affaire)
  • Créez une fonction update qui passe update 函数,将 key de 1 à 0 et vice versa.
  • Liez cette fonction à chaque entrée ou sélection @blur événement
  • Puisque mon modal entier est rendu basé sur une propriété calculée, j'effectue quelques lectures sur key à l'intérieur de cette fonction (dans Mon cas est que j'attribue sa valeur à une nouvelle variable, puis je l'enregistre (pas Détermine lequel des deux déclenche le rendu, mais je suppose que le premier est Assez))
... 
data: function() {
      return {
        ... ,
        key: 0
      };   
},

...

methods: {
    ... ,
    update: function(){
        this.key = this.key == 0 ? 1 : 0
    }
},
computed: {
    ... ,
    testData: function () { //this functions builds an object that is used to render the page  
        var data = []
        var __self = this
        var blu = this.key // This is the line where i read key
        console.log(blu)
        this.test.inputs.forEach(function(input){

            var slug = input.slug.replaceAll('#', '').split('-')
        
            __self.setItem(data, slug, input)

        })
     
        console.log('data', data)
        return data // this value gets then passed to Object.entries() to get an iterable object I build the page with
    } 
}

P粉517475670
P粉517475670

répondre à tous(1)
P粉198749929

Meilleure réponse

Après un débogage en douceur, j’ai réussi à résoudre ce problème.

Essentiellement, le composant que je décris dans la question est utilisé pour deux pages différentes : la page « Créer » et la page « Modifier ». Mon cœur a fait un bond lorsque j'ai vu que tout fonctionnait comme prévu dans la page d'édition.

Que s'est-il passé :

La seule différence entre la façon dont le composant est utilisé dans les deux pages réside dans les données qui lui sont transmises. Dans la page Modifier, chaque objet est renseigné car les données sont déjà là, alors que dans la page Créer, chaque objet est évidemment vide.

Comme j'ai besoin d'un objet utilisable, je dois le remplir avec des entrées vides pour pouvoir y accéder plus tard.

J'ai bêtement essayé de définir la propriété manuellement comme ceci :

objects[index].inputs = {}

Attendez-vous à ce que l'attribution d'une propriété à un objet réactif rende automatiquement cette propriété également réactive. Oh mon Dieu, avais-je tort.

Getters et setters réactifs Vue :

Pour rendre les choses réactives, vue remplace les getters et setters de classe Object par défaut. Mais cela n'arrive que sous certaines conditions :

  • Cet attribut doit être ajouté via Vue.set()this.$set()
  • Toutes les propriétés parentes doivent également être réactives

Par exemple, après quelques essais, paramètre objects[index].inputs = {} 后,我尝试使用 this.$set() pour remplir ma saisie.

Cela ne fonctionne pas car je n'ai pas non plus rendu .inputs réactif.

J'ai donc dû le faire

this.$set('objects[${index}].inputs', {})

avant

this.$set(`objects[${index}].inputs[${input.id}].value`, null)
this.$set(`objects[${index}].inputs[${input.id}].comment`, null)

Conclusion :

Si vous rencontrez des problèmes de réactivité, mon conseil est de connecter ledit objet et de vérifier que lui et son objet parent ont les bons getters et setters.

N'oubliez pas que si vous souhaitez ajouter une nouvelle propriété à un objet réactif, vous devez la $set().

Objet de réaction :
Objets non réactifs :
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal