VueJS kann die Komponente nicht aktualisieren
P粉517475670
P粉517475670 2024-03-26 20:00:55
0
1
385

Ich habe diese Vue 1 Komponente, die ein Objekt als Requisite erhält, das vom Benutzer gefüllt werden muss.

Das Objekt hat die folgende Struktur:

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

}

Die Komponente ist ein einfaches Modal mit einem Formular, das alle notwendigen Eingaben enthält. Ich möchte einige Inhalte überprüfen, Berechnungen durchführen und Zellstile basierend auf Benutzereingaben ändern.

Wenn das Modal geladen wird, erstelle ich die Seite und lege das Modell für diese Eingaben anhand ihrer IDs fest:

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

(Hinweis: subgroup[1]是包含表结构“定义”的另一个对象的一部分,通过执行 inputs[subgroup[1].dx.mob.id] Ich erwarte die verknüpften Tabellenfelder mit den entsprechenden Eingaben des Objekts)

Das Problem ist, egal was ich versuche, die Seite wird nicht neu gerendert. <input> Das Feld enthält nicht einmal den Wert, er verschwindet, sobald ich darauf klicke.

Was noch seltsamer ist, ist, dass die Werte tatsächlich festgelegt sind, aber die einzige Möglichkeit, die Komponente erneut zu rendern und all die guten Überprüfungen und Stile durchzuführen, die ich von ihm benötige, besteht darin, das Modal zu schließen und erneut zu öffnen oder es festzulegen auf dem übergeordneten Tisch des Tisches v-if.

Das sind offensichtlich keine realisierbaren Optionen

  • Ich brauche eine responsive Seite
  • Das Neuerstellen der Komponente (bei jeder Eingabeänderung) nimmt zu viel Zeit in Anspruch

Das habe ich versucht:

  • Erstellen Sie dynamisch einen Beobachter für jede Eingabe
    • Aber vm.$watch das Objekt kann aus irgendeinem Grund nicht gefunden werden.
...forEach((input, index)=>{
    vm.$watch(`object.inputs[${index}].comment`, function(){
            this.$forceUpdate();
        })
}
  • Die Eingabe in die berechnete Eigenschaft zurückgeben und beobachten

    • Aber die Seite kann die Änderungen nicht erkennen
  • Manuell starten bei @change- und @input-Ereignissen this.$forceUpdate()

    • Aber $forceUpdate ist keine Funktion
  • Deklarieren Sie einen Zähler in Daten und erhöhen Sie ihn bei @change- und @input-Ereignissen.

    • Aber die Seite ist immer noch nicht aktualisiert.
  • Legen v-ifauf unsichtbare Objekte

    • Aber nur das besagte Objekt wird neu gerendert
  • Verwenden Sie das Datenattribut, um das :key-Attribut der Komponente zu ändern

    • Aber nichts ist passiert

Wie erwartet kann ich dies nur tun, indem ich das Bauteil zerstöre und neu erstelle.

Hat jemand eine Lösung?

Die hässliche Lösung: Nach ein paar fehlgeschlagenen Versuchen habe ich etwas gefunden, das funktioniert, auch wenn es falsch ist. irgendein echtes Antworten sind weiterhin sehr willkommen.

Im Wesentlichen ist es mir gelungen, ein erneutes Rendern der Komponente zu erzwingen:

  • Deklarieren Sie eine neue Variable in den Daten, ich habe sie benannt key (in meinem Fall ist es eine Zahl, aber alles reicht aus)
  • Erstellen Sie eine update-Funktion, die update 函数,将 key von 1 auf 0 und umgekehrt wechselt.
  • Binden Sie diese Funktion an jede Eingabe oder Auswahl @blurEreignis
  • Da mein gesamtes Modal auf der Grundlage einer berechneten Eigenschaft gerendert wird, führe ich einige Lesevorgänge key innerhalb dieser Funktion durch (in Mein Fall ist, dass ich seinen Wert einer neuen Variablen zuweise und ihn dann protokolliere (nicht). Bestimmt, welcher der beiden das Rendern auslöst, aber ich vermute, dass es der erste ist Genug))
... 
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

Antworte allen(1)
P粉198749929

更好的答案

经过委婉的调试,我成功解决了这个问题。

本质上,我在问题中描述的组件用于两个不同的页面:“创建”页面和“编辑”页面。当我看到编辑页面中一切都按预期运行时,我的心灵动起来。

发生了什么:

组件在两个页面中的使用方式之间的唯一区别是传递给它的数据。在“编辑”页面中,每个对象都已填充,因为数据已经存在,而在“创建”页面中,每个对象显然都是空白的。

由于我需要一个可用的对象,因此我必须用空输入填充它,以便稍后可以访问它们。

我愚蠢地尝试像这样手动设置属性:

objects[index].inputs = {}

期望将属性分配给响应式对象会自动使该属性也成为响应式。天哪,我错了。

Vue 响应式 getter 和 setter:

为了使事情反应灵敏,vue 覆盖了默认的 Object 类 getter 和 setter。但这仅在特定条件下发生:

  • 该属性必须通过 Vue.set()this.$set() 添加
  • 所有父属性也必须是响应式的

例如,经过几次尝试,在设置 objects[index].inputs = {} 后,我尝试使用 this.$set() 来填充我的输入。

这不起作用,因为我也没有使 .inputs 具有反应性。

所以我不得不

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

之前

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

结论:

如果您有反应性问题,我的建议是记录所述对象并检查它及其父对象是否具有正确的 getter 和 setter。

请记住,如果您想向响应式对象添加新属性,则必须 $set() 它。

反应对象:
非反应性对象:
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage