Vue: kann `:srcObject.prop` nicht verwenden, um prop auf null zu setzen

Erstellt am 3. Dez. 2018  ·  3Kommentare  ·  Quelle: vuejs/vue

Ausführung

2.5.17

Reproduktionslink

https://codesandbox.io/s/ppyq71wrxj

Schritte zum Reproduzieren

(Siehe minimale Repro)

  1. eine Komponente mit einem HTMLMediaElement , die :srcObject.prop an eine Dateneigenschaft bindet (die mit null beginnt):
<audio :srcObject.prop="stream">
  1. setze es auf ein gültiges MediaStream :
this.stream = new MediaStream();
  1. setze es auf null :
this.stream = null;

Was wird erwartet?

Ich erwarte, dass das audio.srcObject null ist

Was passiert eigentlich?

es bleibt als MediaStream und es gibt einen TypeError im Protokoll.


Mir ist aufgefallen, dass es bei meinem ersten Versuch, das Repro-Beispiel zu schreiben, tatsächlich funktioniert hat: https://jsfiddle.net/4tnkapxo/1/ (wahrscheinlich weil das Ganze inline ist?)

Ich bin mir nicht sicher, wie hilfreich das ist, aber basierend auf dem Stack-Trace hängt es mit diesem Code zusammen, der in updateDOMProps :

  for (key in oldProps) {
    if (isUndef(props[key])) {
      elm[key] = '';
    }
  }

isUndef(null) wertet true aus und versucht daher, die Requisite auf '' , aber srcObject speziell null oder MediaStream

improvement

Hilfreichster Kommentar

Vielleicht sollten wir keine Transformation für .prop Bindungen anwenden

Alle 3 Kommentare

Vielleicht sollten wir keine Transformation für .prop Bindungen anwenden

Nachdem ich mir den fraglichen Code ( updateDOMProps in src/platforms/web/runtime/modules/dom-props.js) angeschaut habe, denke ich, dass ich etwas besser verstehe, was passiert. Der zugehörige Testfall (in unit/modules/vdom/modules/dom-props.spec.js) lässt es so aussehen, als würde er vor dem Löschen schützen:

  it('should remove the elements domProps', () => {
    const vnode1 = new VNode('a', { domProps: { src: 'http://localhost/' }})
    const vnode2 = new VNode('a', { domProps: {}})
    patch(null, vnode1)
    const elm = patch(vnode1, vnode2)
    expect(elm.src).toBe('')
  })

...Es gibt keinen generischen Weg, eine HTMLEmelent Eigenschaft zu "löschen", außer sie auf einen beliebigen Wert zu setzen, den der Setter definiert. In diesem Sinne ist das Umwandeln in eine leere Zeichenfolge als elm[key] = ''; Grunde der Standardweg am nächsten. Im Fall eines <img> Tags führt das Festlegen der .src Requisite auf etwas anderes als eine leere Zeichenfolge zu einem ziemlich widerlichen Verhalten:

09:48:05.267 const img = document.createElement('img')
09:48:08.948 img.src
09:48:08.953 ""
09:48:14.469 img.src = null
09:48:17.213 img.src
09:48:17.222 "https://localhost:8080/null"

(Ich bin sicher, es gibt einen guten Grund für dieses Verhalten und es gibt überall legitime Anwendungsfälle.)

In diesem Kontext scheint eine leere Zeichenfolge ein ebenso vernünftiger Standard zu sein wie jeder andere für null/undef-Requisiten. Ich habe damit experimentiert, den isUndef(props[key]) Check in props.hasOwnProperty(key) zu ändern oder ihn sogar direkt mit undefined ... ziemlich einfach zu machen, aber es scheint nicht wirklich zu sein praktikabel, wenn Benutzer auf die Möglichkeit angewiesen sind, eine Requisite zu löschen, indem sie sie auf null setzen; es ist nicht abwärtskompatibel. Und Eigenschaft/Element-Kombinationen mit Sonderzeichen in dom-props.js scheinen zu offensichtlich schrecklich, um sie überhaupt zu erwähnen.

Das heißt, mache ich da zu viele Annahmen? Ist dieser Code nur ein Schutz gegen fehlende Requisiten im neuen vnode? Hat der Autor des Tests nur die Eigenschaft src Betracht gezogen, weil sie einen Fehler verursacht hat? Ist es vernünftig zu erwarten, dass Benutzer beim "Löschen" einer Requisite den richtigen Wert zwischen "" , null und undefined angeben?

Andererseits denke ich, dass es nicht wirklich sinnvoll ist, über das Löschen zu sprechen, wenn es um gebundene Eigenschaften geht ... wie im Beispiel von <audio :srcObject.prop="stream"> die berechnete Eigenschaft stream muss etwas zurückgeben, also gehe ich davon aus, dass es etwas mit den vnode-Interna gibt, das außerhalb meines Verständnisses liegt, das es ermöglicht, {stream: {some: thing}} durch {} zu ersetzen.

Wenn der obige Vorschlag in Ordnung klingt, dann würde ich davon ausgehen, dass hasOwnProperty die richtige Prüfung ist, und das Ergebnis sollte elm[key] = '' (wie gesagt, es ist so gut wie ein "Standard"-Löschvorgang , und wahrscheinlich der am häufigsten zutreffende Fall); Ich werde wahrscheinlich diese Woche einen Pull Request schreiben. Aber ich möchte die Zeit nicht aufwenden, wenn es keine sichere Änderung ist.

Ich denke, das wurde von f11449d916a468651d4fd5024c37e3eebbc9941f behoben

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen