Skip to content
Mithril.js 2
Main Navigation AnleitungAPI

Deutsch

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Deutsch

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Aussehen

Sidebar Navigation

Erste Schritte

Installation

Einfache Anwendung

Ressourcen

JSX

ES6+ in älteren Browsern

Animationen

Testen

Beispiele

Integration von Drittanbietern

Pfadverarbeitung

Schlüsselkonzepte

Virtuelle DOM Knoten

Komponenten

Lebenszyklus-Methoden

Keys

Das Auto-Redraw-System

Sonstiges

Framework-Vergleich

Migration von v1.x

Migration von v0.2.x auf v2.x

API

Auf dieser Seite

Migration von v1.x ​

v2.x ist weitgehend API-kompatibel mit v1.x, es gibt jedoch einige Breaking Changes.

Zuweisung zu vnode.state ​

In v1.x war es möglich, vnode.state zu manipulieren und beliebige Werte zuzuweisen. In v2.x führt eine solche Änderung zu einem Fehler. Die Migration kann unterschiedlich aussehen, aber in den meisten Fällen genügt es, Referenzen von vnode.state zu vnode.state.foo zu ändern und einen passenden Namen für foo zu wählen (z. B. count, wenn es sich um den aktuellen Wert eines Zählers handelt).

v1.x ​

javascript
var Counter = {
  oninit: function (vnode) {
    vnode.state = 0;
  },
  view: function (vnode) {
    return m('.counter', [
      m(
        'button',
        {
          onclick: function () {
            vnode.state--;
          },
        },
        '-'
      ),
      vnode.state,
      m(
        'button',
        {
          onclick: function () {
            vnode.state++;
          },
        },
        '+'
      ),
    ]);
  },
};

v2.x ​

javascript
var Counter = {
  oninit: function (vnode) {
    vnode.state.count = 0;
  },
  view: function (vnode) {
    return m('.counter', [
      m(
        'button',
        {
          onclick: function () {
            vnode.state.count--;
          },
        },
        '-'
      ),
      vnode.state.count,
      m(
        'button',
        {
          onclick: function () {
            vnode.state.count++;
          },
        },
        '+'
      ),
    ]);
  },
};

Als v1.0 veröffentlicht wurde, gab es noch keine Klassen- oder Closure-Komponenten. Daher wurde einfach das aus vnode.tag übernommen, was benötigt wurde. Dieses Implementierungsdetail ermöglichte diese Vorgehensweise, und einige Entwickler begannen, sich darauf zu verlassen. Die Dokumentation deutete dies an einigen Stellen ebenfalls an. Inzwischen hat sich dies geändert, was die Verwaltung aus Implementierungssicht vereinfacht, da es nur noch eine Referenz zum Status gibt, nicht zwei.

Änderungen an Routen-Ankern ​

In v1.x wurden oncreate: m.route.link und, falls sich der Link ändern konnte, auch onupdate: m.route.link als Lifecycle-Hooks auf dem VNode verwendet, der geroutet werden sollte. In v2.x wird stattdessen die m.route.Link Komponente verwendet. Der Selektor kann über das Attribut selector: angegeben werden, falls etwas anderes als m("a", ...) verwendet wird. Optionen können über options: angegeben werden. Die Komponente kann über disabled: deaktiviert werden, und andere Attribute können inline angegeben werden, einschließlich href: (erforderlich). Der selector: selbst kann ein beliebiger Selektor sein, der als erstes Argument für m gültig ist, und die Attribute [href=...] und [disabled] können sowohl im Selektor als auch in den normalen Optionen angegeben werden.

v1.x ​

javascript
m('a', {
  href: '/path',
  oncreate: m.route.link,
});

m('button', {
  href: '/path',
  oncreate: m.route.link,
});

m('button.btn[href=/path]', {
  oncreate: m.route.link,
});

v2.x ​

javascript
m(m.route.Link, {
  href: '/path',
});

m(m.route.Link, {
  selector: 'button',
  href: '/path',
});

m(m.route.Link, {
  selector: 'button.btn[href=/path]',
});

Änderungen an m.request Fehlern ​

In v1.x hat m.request Fehler von JSON-Aufrufen geparst und die Eigenschaften des resultierenden geparsten Antwortobjekts dem Fehler zugewiesen. Wenn also eine Antwort mit dem Status 403 und einem Body von {"code": "backoff", "timeout": 1000} empfangen wurde, hätte der Fehler zwei zusätzliche Eigenschaften gehabt: err.code = "backoff" und err.timeout = 1000.

In v2.x wird die Antwort einer response-Eigenschaft im Fehler zugewiesen, und eine code-Eigenschaft enthält den resultierenden Statuscode. Wenn also eine Antwort mit dem Status 403 und einem Body von {"code": "backoff", "timeout": 1000} empfangen wurde, wären dem Fehler zwei Eigenschaften zugewiesen worden: err.response = {code: "backoff", timeout: 1000} und err.code = 403.

m.withAttr entfernt ​

In v1.x konnten Ereignis-Listener oninput: m.withAttr("value", func) und Ähnliches verwenden. In v2.x werden diese Werte direkt aus dem Ziel des Events gelesen. Dies harmonierte gut mit Streams, aber da das Idiom m.withAttr("value", stream) nicht annähernd so verbreitet war wie m.withAttr("value", prop), verlor m.withAttr den größten Teil seines Nutzens und wurde daher entfernt.

v1.x ​

javascript
var value = '';

// In Ihrer View
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', function (v) {
    value = v;
  }),
});

// ODER

var value = m.stream('');

// In Ihrer View
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', value),
});

v2.x ​

javascript
var value = '';

// In Ihrer View
m('input[type=text]', {
  value: value,
  oninput: function (ev) {
    value = ev.target.value;
  },
});

// ODER

var value = m.stream('');

// In Ihrer View
m('input[type=text]', {
  value: value(),
  oninput: function (ev) {
    value(ev.target.value);
  },
});

m.route.prefix ​

In v1.x war m.route.prefix eine Funktion, die mit m.route.prefix(prefix) aufgerufen wurde. Es ist jetzt eine Eigenschaft, die über m.route.prefix = prefix gesetzt wird.

v1.x ​

javascript
m.route.prefix('/root');

v2.x ​

javascript
m.route.prefix = '/root';

m.request/m.jsonp params und body ​

Die Parameter data und useBody wurden umbenannt und neu definiert. data wurde zu params, welches Query-Parameter enthält, die in die URL interpoliert und an die Anfrage angehängt werden. useBody wurde zu body, welcher den Inhalt enthält, der im zugrunde liegenden XHR gesendet werden soll. Dies ermöglicht eine bessere Kontrolle über die tatsächlich gesendete Anfrage und erlaubt es, sowohl Query-Parameter mit POST-Anfragen zu interpolieren als auch GET-Anfragen mit Inhalten zu erstellen.

m.jsonp, das keinen sinnvollen "Body" hat, verwendet nur params, sodass das Umbenennen von data in params für diese Methode ausreicht.

v1.x ​

javascript
m.request('https://example.com/api/user/:id', {
  method: 'GET',
  data: { id: user.id },
});

m.request('https://example.com/api/user/create', {
  method: 'POST',
  data: userData,
});

v2.x ​

javascript
m.request('https://example.com/api/user/:id', {
  method: 'GET',
  params: { id: user.id },
});

m.request('https://example.com/api/user/create', {
  method: 'POST',
  body: userData,
});

Path Templates (Pfadvorlagen) ​

In v1.x gab es drei separate Path Template-Syntaxen, die zwar ähnlich waren, aber 2 separat entworfene Syntaxen und 3 verschiedene Implementierungen hatten. Die Definition war eher ad hoc, und Parameter wurden im Allgemeinen nicht maskiert. In v2.x wird alles entweder kodiert, wenn es :key ist, oder roh, wenn es :key... ist. Wenn Werte unerwartet kodiert werden, verwenden Sie :path.... So einfach ist das.

Konkret wirkt sich dies wie folgt auf jede Methode aus:

m.request und m.jsonp URLs, m.route.set Pfade ​

In v2.x werden Pfadkomponenten automatisch maskiert, wenn sie interpoliert werden. Angenommen, Sie rufen m.route.set("/user/:name/photos/:id", {name: user.name, id: user.id}) auf. Wenn user zuvor {name: "a/b", id: "c/d"} war, würde dies die Route auf /user/a%2Fb/photos/c/d setzen, aber jetzt wird sie auf /user/a%2Fb/photos/c%2Fd gesetzt. Wenn Sie einen Schlüssel absichtlich unmaskiert interpolieren möchten, verwenden Sie stattdessen :key....

Keys in v2.x dürfen keine Instanzen von . oder - enthalten. In v1.x konnten sie alles außer / enthalten.

Interpolationen in Inline-Query-Strings, wie in /api/search?q=:query, werden in v2.x nicht durchgeführt. Übergeben Sie diese stattdessen über params mit den entsprechenden Key-Namen, ohne sie in der Query-String anzugeben.

m.route Routenmuster ​

Pfadschlüssel der Form :key... geben in v1.x ihre URL dekodiert zurück, geben aber in v2.x die rohe URL zurück.

In früheren Versionen wurden Konstrukte wie :key.md fälschlicherweise akzeptiert, wobei der Wert des Parameters dann keymd: "..." war. Dies ist nicht mehr der Fall: .md ist nun Teil des Musters und nicht mehr des Namens.

Lifecycle Call Order (Reihenfolge der Lebenszyklusaufrufe) ​

In v1.x wurden Lebenszyklus-Hooks für Attribute auf Komponenten-VNodes in allen Fällen vor den eigenen Lifecycle-Hooks der Komponente aufgerufen. In v2.x ist dies nur für onbeforeupdate der Fall. Sie müssen möglicherweise Ihren Code entsprechend anpassen.

v1.x ​

javascript
var Comp = {
  oncreate: function () {
    console.log('Component oncreate');
  },
  view: function () {
    return m('div');
  },
};

m.mount(document.body, {
  view: function () {
    return m(Comp, {
      oncreate: function () {
        console.log('Attrs oncreate');
      },
    });
  },
});

// Logs:
// Attrs oncreate
// Component oncreate

v2.x ​

javascript
var Comp = {
  oncreate: function () {
    console.log('Component oncreate');
  },
  view: function () {
    return m('div');
  },
};

m.mount(document.body, {
  view: function () {
    return m(Comp, {
      oncreate: function () {
        console.log('Attrs oncreate');
      },
    });
  },
});

// Logs:
// Component oncreate
// Attrs oncreate

m.redraw Synchronität ​

m.redraw() ist in v2.x immer asynchron. Ein synchrones Neuzeichnen kann explizit über m.redraw.sync() angefordert werden, vorausgesetzt, es läuft gerade kein Neuzeichnen.

Selector Attribute Precedence (Vorrang von Selektorattributen) ​

In v1.x hatten Selektorattribute Vorrang vor Attributen, die im Attribut-Objekt angegeben wurden. Beispielsweise gab m("[a=b]", {a: "c"}).attrs {a: "b"} zurück.

In v2.x haben Attribute, die im Attribut-Objekt angegeben sind, Vorrang vor Selektorattributen. Beispielsweise gibt m("[a=b]", {a: "c"}).attrs {a: "c"} zurück.

Beachten Sie, dass dies technisch gesehen eine Rückkehr zum Verhalten von v0.2.x ist.

Children Normalization (Kindnormalisierung) ​

In v1.x wurden Component-VNode-Children wie andere VNodes normalisiert. In v2.x ist dies nicht mehr der Fall, und Sie müssen dies bei der Entwicklung berücksichtigen. Dies betrifft nicht die Normalisierung, die beim Rendern durchgeführt wird.

m.request Headers (Header) ​

In v1.x setzte Mithril.js diese beiden Header bei allen Nicht-GET-Anfragen, aber nur, wenn useBody auf true gesetzt war (Standardeinstellung) und die anderen aufgeführten Bedingungen erfüllt waren:

  • Content-Type: application/json; charset=utf-8 für Anfragen mit JSON-Bodies
  • Accept: application/json, text/* für Anfragen, die JSON-Antworten erwarten

In v2.x setzt Mithril.js den Content-Type Header für alle Anfragen mit JSON-Bodies, die nicht null sind. Andernfalls wird er standardmäßig weggelassen. Dies geschieht unabhängig von der gewählten Methode, auch bei GET-Anfragen.

Der erste Header, Content-Type, löst einen CORS-Prefetch aus, da er aufgrund des angegebenen Content-Type kein CORS-safelisted Request Header ist (https://fetch.spec.whatwg.org/#cors-safelisted-request-header). Dies könnte neue Fehler verursachen, je nachdem, wie CORS auf Ihrem Server konfiguriert ist. Wenn Sie auf Probleme stoßen, können Sie diesen Header überschreiben, indem Sie headers: {"Content-Type": "text/plain"} übergeben. Der Accept-Header muss nicht überschrieben werden, da er keine Probleme verursacht.

Die Fetch-Spezifikation erlaubt nur die Content-Types application/x-www-form-urlencoded, multipart/form-data und text/plain ohne CORS-Prefetch-Prüfung. JSON ist explizit ausgeschlossen.

Query Parameters (Abfrageparameter) in Hash Strings (Hash-Zeichenketten) in Routen (Routen) ​

In v1.x konnten Query Parameters für Routen sowohl in der Query String als auch in der Hash String angegeben werden, sodass m.route.set("/route?foo=1&bar=2"), m.route.set("/route?foo=1#bar=2") und m.route.set("/route#foo=1&bar=2") alle gleichwertig waren und die daraus extrahierten Attribute {foo: "1", bar: "2"} gewesen wären.

In v2.x wird der Inhalt von Hash Strings ignoriert, aber beibehalten. Die Attribute, die aus jedem extrahiert würden, wären also diese:

  • m.route.set("/route?foo=1&bar=2") → {foo: "1", bar: "2"}
  • m.route.set("/route?foo=1#bar=2") → {foo: "1"}
  • m.route.set("/route#foo=1&bar=2") → {}

Der Grund ist, dass URLs wie https://example.com/#!/route#key technisch ungültig sind.

Oder kurz gesagt: Verwenden Sie keine ungültigen URLs mehr!

Keys (Schlüssel) ​

In v1.x konnten Keyed und Unkeyed VNodes frei gemischt werden. Wenn der erste Node Keyed ist, wird ein Keyed Diff durchgeführt, wobei davon ausgegangen wird, dass jedes Element einen Key hat und Löcher einfach ignoriert werden. Andernfalls wird ein iterativer Diff durchgeführt, und wenn ein Node einen Key hat, wird überprüft, ob er sich nicht gleichzeitig geändert hat, wenn Tags und ähnliches überprüft werden.

In v2.x müssen Children Lists von Fragments und Elements entweder alle mit Schlüssel versehen oder alle ohne Schlüssel versehen sein. Löcher gelten für die Zwecke dieser Prüfung auch als Unkeyed - sie werden nicht mehr ignoriert.

Um dies zu umgehen, kann ein Fragment mit einem einzelnen VNode verwendet werden, z.B. [m("div", {key: whatever})].

m.version entfernt ​

Es hatte im Allgemeinen wenig Nutzen und kann bei Bedarf selbst wieder hinzugefügt werden. Es wird empfohlen, Feature Detection zu verwenden, um die verfügbaren Funktionen zu ermitteln. Die v2.x-API ist darauf ausgelegt, dies zu erleichtern.

Pager
Vorherige SeiteFramework-Vergleich
Nächste SeiteMigration von v0.2.x auf v2.x

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors

https://mithril.js.org/migration-v1x.html

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors