Vue: Vorausgesetzt, Requisiten werden nicht in Funktionskomponenten injiziert

Erstellt am 7. Juni 2017  ·  16Kommentare  ·  Quelle: vuejs/vue

Ausführung

2.3.3

Reproduktionslink

http://jsfiddle.net/p861bj9y/

Schritte zum Reproduzieren

Ich habe eine minimale Reproduktion des Verhaltens erstellt, das ich testen möchte. Das Beispiel benötigt nur JSX, um zu funktionieren.

Was wird erwartet?

Die vom übergeordneten Element übergebenen Eigenschaften sollten in ctx.injections .

Was passiert eigentlich?

Ctx.injections existiert, bleibt aber leer. Die Eigenschaften werden nicht an den Funktionskomponentenkontext weitergegeben.

bug

Hilfreichster Kommentar

Gibt es Pläne, dieses Problem in Version 3 zu beheben?

Ich versuche beispielsweise, ein v-for in eine Renderfunktion zu abstrahieren, aber meine Kinder können Funktionskomponenten sein (sie werden also bereits beim Aufrufen der Renderfunktion gerendert und ich kann sie nicht klonen).

Alle 16 Kommentare

Dies liegt daran, dass anstelle von parent child als Kinder von vm (möglicherweise ein Problem). Möglicherweise müssen Sie also provide in vm schreiben.

Übrigens, Ihre Geige benutzt [email protected] 😅

Der Suchalgorithmus für Provide Inject ist, dass das Kind selbst nach bereitgestellten Attributen sucht und dann die $parent -Hierarchie auf der Suche nach bereitgestellten Requisiten wiederholt, bis es an der Wurzel liegt.
https://github.com/vuejs/vue/blob/b182ac40697edbe8253d4bd68b6ac09e93259e1c/src/core/instance/inject.js#L59 -L59

Ihre Geige konnte nicht ausgeführt werden, aber als ich https://jsfiddle.net/Austio/vhgztp59/7/ ausführte, war diese $ Geige für die untergeordnete Komponente undefiniert, als ich zum Suchkontext kam. Zumindest ist dies ein Anfang, wenn dies kein Problem beim Rendern in Slots ist und keine Beziehung zwischen den Komponenten besteht.

Es sieht so aus, als würde die Funktionskomponente gerendert, bevor die Slots aufgelöst werden

@Kingwl richtig, und das ist eine Art technische Anforderung.

Ich erinnere mich, dass ich den Punkt angesprochen habe, weil ich verrückt danach wurde. Am Ende sah es für mich normal aus, weil Funktionskomponenten an Komponenten angehängt sind, in denen sie gerendert wurden, und daher bei Verwendung in einem Steckplatz an die äußere Komponente angehängt werden. Dies ist jedoch bei nicht funktionierenden Komponenten nicht der Fall:

Container injiziert mode: 'foo' und rendert <div><slot/></div>

<!-- rendered in App -->
<container>
   <!-- parent is App, mode is undefined -->
  <functional></functional>
</container>

<container>
   <!-- parent is container, mode is foo -->
  <not-functional></not-functional>
</container>

http://jsfiddle.net/p861bj9y/

edit: @alidcastano Ich habe die Geige in deinem Kommentar aktualisiert, da deine nicht einmal Vue 2 verwendet hat

Haha, tut mir leid, dass ich die falsche Vue-Version in der Geige verwendet habe. Ich war zu sehr damit beschäftigt, JSX nicht konfigurieren zu können, was mir nicht klar war. @posva Danke, dass du mein Beispiel

- -

Das Problem hier ist also nicht, dass die Funktionskomponente die bereitgestellten Eigenschaften nicht empfangen kann, sondern dass die Funktionskomponente vor dem Steckplatz gerendert wird.

@LinusBorg Bedeutet das unter "technischen Anforderungen", dass es keine

Sollte ein Container erstellt werden, der als vm , der die Requisiten weitergibt? Zum Beispiel würde sich das Design folgendermaßen ändern:

// before
<parent-component>
  <child-component />
</parent-component>

// after
<vm-container>
   <parent-component>
     <child-component />
   </parent-component>
<vm-container>

Das obige Beispiel scheint jedoch unnötig aufgebläht zu sein, da die Essenz der übergeordneten Komponente bereits alle Daten enthielt, die zur Bereitstellung für das Kind erforderlich waren. Aber ich bin offen für Diskussionen; Schlägt ihr das vor?

Das vm-container ändert nichts, da der Slot im Kontext von app gerendert wird

Bedeutet dies unter "technischen Anforderungen", dass es keine Problemumgehung gibt oder dass das Verhalten beabsichtigt ist?

Das Verhalten ist ein Ergebnis der Funktionsweise funktionaler Komponenten. Betrachten Sie diesen Satz von Komponenten:

<!-- template of a `parent` component -->
<template>
  <Child>
    <functional />
  </Child>
</template>

Wenn Sie eine Funktionskomponente an den Steckplatz einer anderen Komponente übergeben, muss diese gerendert werden, bevor sie an das untergeordnete Element übergeben wird, damit diese untergeordnete Komponente die resultierenden vNodes als Steckplatzinhalt empfangen kann. (*)

Im Zusammenhang mit meinem obigen Beispiel bedeutet dies, dass in dem Moment, in dem die <functional> -Komponente gerendert wird, das verfügbare übergeordnete Element die äußere Komponente ( <parent> ) ist, nicht die <child> .

Folglich sind die einzigen Injektionen, die für die Funktionskomponente verfügbar sind, diejenigen, die auch in <parent> verfügbar sind.


(*): So funktioniert die aktuelle Implementierung des Virtualdom mit funktionalen Komponenten. Um dies zu ändern, müssten ziemlich viele interne Mechaniken geändert werden.

@posva @LinusBorg Verstanden , danke für die Erklärung.

Aufgrund dieser Anforderungen besteht die einzige Möglichkeit, funktionale Komponenten bereitzustellen / zu injizieren, darin, die Requisiten im Kontext app bereitzustellen.

Ich bin sicher, dass diese Einschränkung in der Dokumentation klargestellt wird. Bitte schließen Sie dieses Problem, wenn nichts anderes getan oder geklärt werden muss. Danke noch einmal!

Vielleicht können wir einen Weg finden, um die Funktionskomponente im Steckplatz zu verbessern
Aber im Moment sollte es so gemacht werden, wie @posva und @LinusBorg sagten

@Kingwl Danke, dass hältst .

Ich hatte endlich etwas Zeit, um zu versuchen, dies mit den oben genannten Ratschlägen in mein vue-mobiledoc-editor- Plugin zu integrieren. Ein Problem, das ich voraussehe, wenn die Komponente von der Instanz app werden muss, ist, dass es schwieriger ist, Flexibilität mit den verwendeten verschachtelten Komponenten zuzulassen.

Zum Beispiel muss ich die Komponenten exportieren, die bereits unter der App-Instanz registriert sind:

...

export default Vue.extend({
  render (h) {
    return (
      <div>
        <ParentComp>
          <ChildFuncComp/>
        </ParentComp>
      </div>
    )
  },

  provide () { // data that needs to be injected into functional components 
    return {
       msg: 'hello'
    }
  },

  components: {
    ParentComp,
    ChildFuncComp
  }
})

Wenn der Benutzer das Plugin verwendet, sieht es nach meinem Verständnis folgendermaßen aus:

// template
<div id="app">
   <div id="#someWhereInApp" />
</div>

// script 
import SuperCoolComponent from 'SuperCoolComponent' 

export default {
   mounted () {
    this.$once('mounted', () => new SuperCoolComponent().$mount('#someWhereInApp'))
    this.$emit('mounted')
  }
}

Wenn meine Implementierung korrekt ist, schränkt dies die Verwendung von Bereitstellen / Injizieren mit Funktionskomponenten erheblich ein, da Sie die Komponenten, die Sie verwenden möchten, nicht einzeln importieren und registrieren dürfen.

Ich würde stattdessen vollständige Komponenten verwenden, um das Bereitstellen / Injizieren zu unterstützen

Ich versuche das zu lösen
Vielleicht ist es ein langer Prozess

@Kingwl Konnten Sie es lösen?

Gibt es Pläne, dieses Problem in Version 3 zu beheben?

Ich versuche beispielsweise, ein v-for in eine Renderfunktion zu abstrahieren, aber meine Kinder können Funktionskomponenten sein (sie werden also bereits beim Aufrufen der Renderfunktion gerendert und ich kann sie nicht klonen).

Irgendein Update?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

aviggngyv picture aviggngyv  ·  3Kommentare

franciscolourenco picture franciscolourenco  ·  3Kommentare

lmnsg picture lmnsg  ·  3Kommentare

robertleeplummerjr picture robertleeplummerjr  ·  3Kommentare

wufeng87 picture wufeng87  ·  3Kommentare