Skip to content
Mithril.js 2
Main Navigation GuideAPI

Français

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

Français

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

Apparence

Sidebar Navigation

Bien démarrer

Installation

Application Simple

Ressources

JSX

ES6+ sur les navigateurs anciens

Animations

Tests

Exemples

Intégration de librairies externes

Gestion des Chemins

Concepts clés

Nœuds du DOM virtuel

Composants

Méthodes de cycle de vie

Keys

Le système de rafraîchissement automatique

Divers

Comparaison des frameworks

Migration depuis la version 1.x

Migration depuis la v0.2.x

API

Sur cette page

Migration depuis la version 1.x ​

La version 2.x est largement compatible avec l'API de la version 1.x, mais certains changements importants sont à noter.

Affectation à vnode.state ​

Dans la version 1.x, il était possible de manipuler vnode.state et d'y affecter n'importe quelle valeur. Dans la version 2.x, une tentative de modification directe de vnode.state générera une erreur. La migration dépendra de votre code, mais dans la plupart des cas, il suffit de remplacer les références à vnode.state par vnode.state.foo, en choisissant un nom approprié pour foo (par exemple, count si cela représente la valeur d'un compteur).

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

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

Lors de la première publication de la version 1.0, les composants de classe et de fermeture n'existaient pas. Le composant récupérait simplement les données nécessaires depuis vnode.tag. Cette particularité d'implémentation permettait la manipulation directe de vnode.state, et certains développeurs ont commencé à en dépendre. Cela était également implicite dans certains passages de la documentation. Désormais, l'approche est différente, ce qui simplifie la gestion d'un point de vue de l'implémentation, car il n'y a qu'une seule référence à l'état (state), et non deux.

Modifications des ancres de route ​

Dans la version 1.x, on utilisait oncreate: m.route.link et, si le lien pouvait être modifié, onupdate: m.route.link comme fonctions de cycle de vie sur le vnode routable. Dans la version 2.x, on utilise le composant m.route.Link. Le sélecteur peut être spécifié via un attribut selector:, si vous utilisez autre chose que m("a", ...). Les options peuvent être spécifiées via options:, la désactivation via disabled:, et d'autres attributs peuvent être spécifiés directement, y compris href: (obligatoire). Le selector: lui-même peut contenir n'importe quel sélecteur valide comme premier argument pour m, et les attributs [href=...] et [disabled] peuvent être spécifiés dans le sélecteur ainsi que dans les options habituelles.

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

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

Modifications des erreurs m.request ​

Dans la version 1.x, m.request analysait les erreurs des appels JSON et assignait les propriétés de l'objet analysé résultant à la réponse. Ainsi, si vous receviez une réponse avec le statut 403 et un corps de {"code": "backoff", "timeout": 1000}, l'erreur aurait deux propriétés assignées : err.code = "backoff" et err.timeout = 1000.

Dans la version 2.x, la réponse est assignée à une propriété response sur le résultat, et une propriété code contient le code de statut résultant. Donc, si vous receviez une réponse avec le statut 403 et un corps de {"code": "backoff", "timeout": 1000}, l'erreur se verrait assigner deux propriétés : err.response = {code: "backoff", timeout: 1000} et err.code = 403.

m.withAttr supprimé ​

Dans la version 1.x, les gestionnaires d'événements pouvaient utiliser oninput: m.withAttr("value", func) et similaire. Dans la version 2.x, il suffit de lire les valeurs directement à partir de la cible de l'événement. Bien que cela fonctionnait avec les flux, l'idiome m.withAttr("value", stream) était beaucoup moins courant que m.withAttr("value", prop). Par conséquent, m.withAttr a perdu la plupart de son utilité et a été supprimé.

version 1.x ​

javascript
var value = '';

// Dans votre composant
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', function (v) {
    value = v;
  }),
});

// OU

var value = m.stream('');

// Dans votre composant
m('input[type=text]', {
  value: value(),
  oninput: m.withAttr('value', value),
});

version 2.x ​

javascript
var value = '';

// Dans votre composant
m('input[type=text]', {
  value: value,
  oninput: function (ev) {
    value = ev.target.value;
  },
});

// OU

var value = m.stream('');

// Dans votre composant
m('input[type=text]', {
  value: value(),
  oninput: function (ev) {
    value(ev.target.value);
  },
});

m.route.prefix ​

Dans la version 1.x, m.route.prefix était une fonction appelée via m.route.prefix(prefix). C'est maintenant une propriété que vous définissez via m.route.prefix = prefix.

version 1.x ​

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

version 2.x ​

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

Paramètres et corps de m.request/m.jsonp ​

Les options data et useBody ont été refactorisées en params (les paramètres de requête interpolés dans l'URL et ajoutés à la requête) et body (le corps à envoyer dans le XHR sous-jacent). Cela offre un meilleur contrôle sur la requête réelle envoyée et permet à la fois d'interpoler dans les paramètres de requête avec les requêtes POST et de créer des requêtes GET avec des corps.

m.jsonp, n'ayant pas de "corps" significatif, utilise simplement params. Le renommage de data en params est donc suffisant pour cette méthode.

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

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

Modèles de chemin ​

Dans la version 1.x, il existait trois syntaxes de modèle de chemin distinctes qui, bien que similaires, avaient 2 syntaxes conçues séparément et 3 implémentations différentes. La définition était assez ad hoc, et les paramètres n'étaient généralement pas échappés. Désormais, tout est soit encodé si c'est :key, soit brut si c'est :key.... Si les éléments sont encodés de manière inattendue, utilisez :path.... C'est aussi simple que cela.

Concrètement, voici comment cela affecte chaque méthode :

URL m.request et m.jsonp, chemins m.route.set ​

Les composants de chemin dans la version 2.x sont échappés automatiquement lors de l'interpolation. Supposons que vous invoquiez m.route.set("/user/:name/photos/:id", {name: user.name, id: user.id}). Auparavant, si user était {name: "a/b", id: "c/d"}, cela définirait la route sur /user/a%2Fb/photos/c/d, mais cela la définira maintenant sur /user/a%2Fb/photos/c%2Fd. Si vous voulez délibérément interpoler une clé non échappée, utilisez :key... à la place.

Les clés dans la version 2.x ne peuvent contenir aucune instance de . ou -. Dans la version 1.x, elles pouvaient contenir n'importe quoi d'autre que /.

Les interpolations dans les chaînes de requête en ligne, comme dans /api/search?q=:query, ne sont pas effectuées dans la version 2.x. Passez-les plutôt via params avec les noms de clé appropriés, sans les spécifier dans la chaîne de requête.

Motifs de route m.route ​

Les clés de chemin de la forme :key... renvoient leur URL décodée dans la version 1.x, mais renvoient l'URL brute dans la version 2.x.

Auparavant, des éléments comme :key.md étaient acceptés par erreur, avec la valeur du paramètre résultant définie sur keymd: "...". Ce n'est plus le cas : le .md fait maintenant partie du motif, pas du nom.

Ordre d'appel des fonctions de cycle de vie ​

Dans la version 1.x, les fonctions de cycle de vie des attributs sur les vnodes de composant étaient appelées avant les propres fonctions de cycle de vie du composant dans tous les cas. Dans la version 2.x, ce n'est le cas que pour onbeforeupdate. Il est donc impératif d'ajuster votre code en conséquence.

version 1.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');
      },
    });
  },
});

// Résultat :
// Attrs oncreate
// Component oncreate

version 2.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');
      },
    });
  },
});

// Résultat :
// Component oncreate
// Attrs oncreate

Synchronicité de m.redraw ​

m.redraw() dans la version 2.x est toujours asynchrone. Vous pouvez demander spécifiquement un rafraîchissement synchrone via m.redraw.sync() à condition qu'aucun rafraîchissement ne soit en cours.

Priorité des attributs de sélecteur ​

Dans la version 1.x, les attributs de sélecteur avaient priorité sur les attributs spécifiés dans l'objet d'attributs. Par exemple, m("[a=b]", {a: "c"}).attrs renvoyait {a: "b"}.

Dans la version 2.x, les attributs spécifiés dans l'objet d'attributs ont priorité sur les attributs de sélecteur. Par exemple, m("[a=b]", {a: "c"}).attrs renvoie {a: "c"}.

Notez qu'il s'agit techniquement d'un retour au comportement de la version 0.2.x.

Normalisation des enfants ​

Dans la version 1.x, les enfants des vnodes de composant étaient normalisés comme les autres vnodes. Dans la version 2.x, ce n'est plus le cas et vous devrez planifier en conséquence. Cela n'affecte pas la normalisation effectuée lors du rendu.

En-têtes m.request ​

Dans la version 1.x, Mithril.js définissait ces deux en-têtes sur toutes les requêtes non-GET, mais seulement lorsque useBody était défini sur true (la valeur par défaut) et que les autres conditions énumérées étaient remplies :

  • Content-Type: application/json; charset=utf-8 pour les requêtes avec des corps JSON
  • Accept: application/json, text/* pour les requêtes attendant des réponses JSON

Dans la version 2.x, Mithril.js définit le premier pour toutes les requêtes avec des corps JSON qui sont != null et l'omet par défaut sinon, et cela se fait indépendamment de la méthode choisie, y compris sur les requêtes GET.

Le premier des deux en-têtes, Content-Type, déclenchera une prélecture CORS car il n'est pas un en-tête de requête CORS sécurisé en raison du type de contenu spécifié, et cela pourrait introduire de nouvelles erreurs en fonction de la façon dont CORS est configuré sur votre serveur. Si vous rencontrez des problèmes avec cela, vous devrez peut-être remplacer l'en-tête en question en passant headers: {"Content-Type": "text/plain"}. (L'en-tête Accept ne déclenche rien, vous n'avez donc pas besoin de le remplacer.)

Les seuls types de contenu que la spécification Fetch permet d'éviter les vérifications de prélecture CORS sont application/x-www-form-urlencoded, multipart/form-data et text/plain. Elle n'autorise rien d'autre, et elle interdit intentionnellement JSON.

Paramètres de requête dans les fragments d'URL dans les routes ​

Dans la version 1.x, vous pouviez spécifier des paramètres de requête pour les routes à la fois dans la chaîne de requête et dans le fragment d'URL. Ainsi, m.route.set("/route?foo=1&bar=2"), m.route.set("/route?foo=1#bar=2") et m.route.set("/route#foo=1&bar=2") étaient tous équivalents, et les attributs extraits d'eux auraient été {foo: "1", bar: "2"}.

Dans la version 2.x, le contenu des fragments d'URL est ignoré mais conservé. Ainsi, les attributs extraits de chacun seraient les suivants :

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

La raison en est que les URL comme https://example.com/#!/route#key sont techniquement invalides selon la spécification URL et étaient même invalides selon la RFC qui l'a précédée. Ce n'est qu'une bizarrerie de la spécification HTML qu'elles soient autorisées. (La spécification HTML aurait dû exiger que les ID et les fragments d'emplacement soient des fragments d'URL valides dès le début si elle voulait suivre la spécification.)

En bref, arrêtez d'utiliser des URL invalides !

Les clés ​

Dans la version 1.x, vous pouviez mélanger librement les vnodes avec et sans clé. Si le premier nœud a une clé, une comparaison avec clé est effectuée, en supposant que chaque élément a une clé et en ignorant simplement les éléments vides au fur et à mesure. Sinon, une comparaison itérative est effectuée, et si un nœud a une clé, il serait vérifié qu'il n'a pas changé en même temps que les balises et similaires sont vérifiées.

Dans la version 2.x, les listes d'enfants des fragments et des éléments doivent être soit toutes avec clé, soit toutes sans clé. Les emplacements vides sont également considérés comme non-clés aux fins de cette vérification : ils ne sont plus ignorés.

Si vous devez contourner cette limitation, utilisez l'idiome d'un fragment contenant un seul vnode, comme [m("div", {key: whatever})].

m.version supprimé ​

Il servait peu en général, et vous pouvez toujours le rajouter vous-même. Vous devriez préférer la détection de fonctionnalités pour savoir quelles fonctionnalités sont disponibles, et l'API version 2.x est conçue pour mieux permettre cela.

Pager
Page précédenteComparaison des frameworks
Page suivanteMigration depuis la v0.2.x

Publié sous la licence MIT.

Copyright (c) 2024 Mithril Contributors

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

Publié sous la licence MIT.

Copyright (c) 2024 Mithril Contributors