Skip to content
Mithril.js 2
Main Navigation GuidaAPI

Italiano

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

Italiano

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

Aspetto

Sidebar Navigation

Per iniziare

Installazione di Mithril.js

Applicazione semplice

Risorse

JSX

ES6+ su browser legacy

Animazioni

Testing

Esempi

Integrazione di terze parti

Gestione dei Percorsi

Concetti chiave

Nodi del DOM virtuale

Componenti

Metodi del Ciclo di Vita

Chiavi

Il sistema di aggiornamento automatico

Varie

Confronto tra i Framework

Migrazione da v1.x

Migrazione da v0.2.x

API

In questa pagina

Migrazione da v1.x ​

La v2.x è quasi completamente API-compatibile con la v1.x, ma ci sono alcune modifiche che introducono incompatibilità.

Assegnazione a vnode.state ​

Nella v1.x, era possibile manipolare vnode.state e assegnargli qualsiasi valore. Nella v2.x, verrà generato un errore se si tenta di modificarlo. La migrazione può variare, ma nella maggior parte dei casi è sufficiente sostituire i riferimenti a vnode.state con vnode.state.foo, scegliendo un nome appropriato per foo (ad esempio count se rappresenta il valore corrente di un contatore).

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++;
          },
        },
        '+'
      ),
    ]);
  },
};

Quando la v1.0 è stata rilasciata, i componenti classe e closure non esistevano, quindi si utilizzava semplicemente ciò che era presente in vnode.tag. Questo dettaglio implementativo ha reso possibile tale comportamento, e alcuni sviluppatori hanno iniziato a farvi affidamento. Era anche implicitamente suggerito in alcuni punti della documentazione. Ora, le cose sono cambiate, e questo semplifica la gestione dal punto di vista dell'implementazione, dato che c'è un solo riferimento allo stato, invece di due.

Modifiche alle ancore di routing ​

Nella v1.x, si utilizzavano oncreate: m.route.link e, se il link poteva cambiare, anche onupdate: m.route.link, come hook del ciclo di vita sul vnode che rappresentava il link navigabile. Nella v2.x, si utilizza invece il componente m.route.Link. Il selettore può essere definito tramite un attributo selector: se si utilizza qualcosa di diverso da m("a", ...) le opzioni possono essere definite tramite options:, è possibile disabilitarlo tramite disabled:, e altri attributi possono essere specificati inline, incluso href: (obbligatorio). L'attributo selector: stesso può contenere qualsiasi selettore valido come primo argomento per m, e gli attributi [href=...] e [disabled] possono essere specificati nel selettore così come nelle normali opzioni.

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]',
});

Modifiche agli errori di m.request ​

Nella v1.x, m.request interpretava gli errori delle chiamate JSON e assegnava le proprietà dell'oggetto analizzato risultante alla risposta. Se si riceveva una risposta con stato 403 e un corpo di {"code": "backoff", "timeout": 1000}, all'errore venivano assegnate due proprietà extra: err.code = "backoff" e err.timeout = 1000.

Nella v2.x, la risposta viene assegnata a una proprietà response del risultato, e una proprietà code contiene il codice di stato risultante. Quindi, se si riceveva una risposta con stato 403 e un corpo di {"code": "backoff", "timeout": 1000}, l'errore avrebbe assegnato due proprietà: err.response = {code: "backoff", timeout: 1000} e err.code = 403.

m.withAttr rimosso ​

Nella v1.x, i listener di eventi potevano utilizzare oninput: m.withAttr("value", func) e simili. Nella v2.x, si leggono i valori direttamente dal target dell'evento stesso. Si integrava bene con gli stream, ma poiché l'utilizzo di m.withAttr("value", stream) non era diffuso quanto m.withAttr("value", prop), m.withAttr ha perso gran parte della sua utilità ed è stato quindi rimosso.

v1.x ​

javascript
var value = '';

// Nella tua view
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', function (v) {
    value = v;
  }),
});

// OPPURE

var value = m.stream('');

// Nella tua view
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', value),
});

v2.x ​

javascript
var value = '';

// Nella tua view
m('input[type=text]', {
  value: value,
  oninput: function (ev) {
    value = ev.target.value;
  },
});

// OPPURE

var value = m.stream('');

// Nella tua view
m('input[type=text]', {
  value: value(),
  oninput: function (ev) {
    value(ev.target.value);
  },
});

m.route.prefix ​

Nella v1.x, m.route.prefix era una funzione invocata tramite m.route.prefix(prefix). Ora è una proprietà che si imposta tramite m.route.prefix = prefix

v1.x ​

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

v2.x ​

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

Parametri e body di m.request/m.jsonp ​

data e useBody sono stati riorganizzati in params, parametri di query interpolati nell'URL e aggiunti alla richiesta, e body, il corpo da inviare nell'XHR sottostante. Questo offre un controllo maggiore sulla richiesta effettiva e consente sia di interpolare i parametri di query nelle richieste POST sia di creare richieste GET con un body.

m.jsonp, non avendo un "body" significativo, usa solo params, quindi rinominare data in params è sufficiente per quel metodo.

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,
});

Template di percorso ​

Nella v1.x, c'erano tre sintassi separate per i template di percorso che, sebbene fossero simili, avevano 2 sintassi progettate separatamente e 3 implementazioni diverse. Era definito in modo piuttosto ad-hoc, e i parametri non erano generalmente escaped. Ora, tutto viene codificato se è :key, lasciato grezzo se è :key.... Se si verifica una codifica inattesa, utilizzare :path.... È così semplice.

Concretamente, ecco come influisce su ciascun metodo:

URL di m.request e m.jsonp, percorsi di m.route.set ​

I componenti del percorso nella v2.x sono codificati automaticamente quando interpolati. Supponiamo di invocare m.route.set("/user/:name/photos/:id", {name: user.name, id: user.id}). In precedenza, se user era {name: "a/b", id: "c/d"}, questo avrebbe impostato la route a /user/a%2Fb/photos/c/d, ma ora la imposterà a /user/a%2Fb/photos/c%2Fd. Se si desidera deliberatamente interpolare una key non codificata, usare invece :key....

Nella v2.x, i nomi delle chiavi non possono contenere istanze di . o -. Nella v1.x, potevano contenere qualsiasi cosa tranne /.

Le interpolazioni nelle stringhe di query inline, come in /api/search?q=:query, non vengono eseguite nella v2.x. Passare invece quelle tramite params con nomi di key appropriati, senza specificarlo nella query string.

Pattern di route di m.route ​

Le key di percorso della forma :key... restituiscono il loro URL decodificato nella v1.x, ma restituiscono l'URL raw nella v2.x.

In precedenza, costrutti come :key.md erano erroneamente accettati, con il valore del parametro risultante impostato su keymd: "...". Questo non è più il caso - .md fa ora parte del pattern, non del nome.

Ordine di chiamata del ciclo di vita ​

Nella v1.x, gli hook del ciclo di vita degli attributi sui vnode dei componenti venivano chiamati prima degli hook del ciclo di vita del componente stesso in tutti i casi. Nella v2.x, questo è il caso solo per onbeforeupdate. Pertanto, potrebbe essere necessario modificare il codice di conseguenza.

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

Sincronicità di m.redraw ​

m.redraw() nella v2.x è sempre asincrono. È possibile richiedere specificamente un redraw sincrono tramite m.redraw.sync() a condizione che non sia attualmente in corso alcun redraw.

Precedenza degli attributi del selettore ​

Nella v1.x, gli attributi del selettore avevano la precedenza sugli attributi specificati nell'oggetto degli attributi. Ad esempio, m("[a=b]", {a: "c"}).attrs restituiva {a: "b"}.

Nella v2.x, gli attributi specificati nell'oggetto degli attributi hanno la precedenza sugli attributi del selettore. Ad esempio, m("[a=b]", {a: "c"}).attrs restituisce {a: "c"}.

Si noti che questo comportamento ripristina tecnicamente quello della v0.2.x.

Normalizzazione dei children ​

Nella v1.x, i children dei vnode dei componenti venivano normalizzati come altri vnode. Nella v2.x, questo non è più il caso e sarà necessario tenerne conto. Questo non influisce sulla normalizzazione eseguita sul render.

Header di m.request ​

Nella v1.x, Mithril.js impostava questi due header su tutte le richieste non-GET, ma solo quando useBody era impostato su true (il valore predefinito) e le altre condizioni elencate erano valide:

  • Content-Type: application/json; charset=utf-8 per le richieste con body JSON
  • Accept: application/json, text/* per le richieste che si aspettano risposte JSON

Nella v2.x, Mithril.js imposta il primo header per tutte le richieste con body JSON non nulli (!= null) e lo omette altrimenti. Questo avviene indipendentemente dal metodo HTTP utilizzato, incluse le richieste GET.

Il primo dei due header, Content-Type, attiverà un preflight CORS in quanto non è un header di richiesta CORS-safelisted a causa del tipo di contenuto specificato, e questo potrebbe introdurre nuovi errori a seconda di come è configurato CORS sul tuo server. In caso di problemi, è possibile sovrascrivere l'header passando headers: {"Content-Type": "text/plain"}. (L'header Accept non attiva nulla, quindi non è necessario sovrascriverlo.)

Gli unici tipi di contenuto che la specifica Fetch consente di evitare i controlli di preflight CORS sono application/x-www-form-urlencoded, multipart/form-data e text/plain. Non consente nient'altro, e intenzionalmente non consente JSON.

Parametri di query nelle stringhe hash nelle route ​

Nella v1.x, era possibile specificare i parametri di query per le route sia nella query string che nella stringa hash, quindi m.route.set("/route?foo=1&bar=2"), m.route.set("/route?foo=1#bar=2") e m.route.set("/route#foo=1&bar=2") erano tutti equivalenti e gli attributi estratti da essi sarebbero stati {foo: "1", bar: "2"}.

Nella v2.x, il contenuto delle stringhe hash viene ignorato ma rimane preservato. Quindi gli attributi estratti da ciascuno sarebbero questi:

  • 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") → {}

Questo perché URL come https://example.com/#!/route#key sono tecnicamente non validi secondo la specifica URL e lo erano anche secondo la RFC precedente. La loro validità è dovuta a una peculiarità della specifica HTML.

O in breve, evitare di usare URL non validi!

Key ​

Nella v1.x, era possibile mescolare liberamente vnode con key e senza key. Se il primo nodo ha una key, viene eseguito un diff con key, assumendo che ogni elemento abbia una key e ignorando semplicemente i buchi mentre procede. Altrimenti, viene eseguito un diff iterativo, e se un nodo ha una key, verrebbe controllato che non sia cambiato nello stesso momento in cui vengono controllati i tag e simili.

Nella v2.x, le liste di elementi figli, sia di frammenti che di elementi, devono essere omogenee: tutti gli elementi devono avere una chiave, oppure nessuno deve averla. Ai fini di questo controllo, anche i "buchi" (elementi mancanti) sono considerati come elementi senza chiave e non vengono più ignorati.

Se è necessario aggirare questa limitazione, usare l'idioma di un frammento contenente un singolo vnode, come [m("div", {key: whatever})].

m.version rimosso ​

Aveva un'utilità limitata in generale ed è comunque possibile reintrodurla manualmente. È preferibile utilizzare il feature detection per sapere quali funzionalità sono disponibili, e l'API v2.x è progettata per facilitare questo approccio.

Pager
Pagina precedenteConfronto tra i Framework
Pagina successivaMigrazione da v0.2.x

Rilasciato sotto la licenza MIT.

Copyright (c) 2024 Mithril Contributors

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

Rilasciato sotto la licenza MIT.

Copyright (c) 2024 Mithril Contributors