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

JSX ​

Description ​

JSX est une extension de syntaxe qui permet d'écrire du code HTML directement dans du JavaScript. Bien qu'elle ne fasse partie d'aucune norme JavaScript et ne soit pas indispensable pour créer des applications, son utilisation peut être plus agréable selon vos préférences ou celles de votre équipe.

jsx
function MyComponent() {
  return {
    view: () => m('main', [m('h1', 'Hello world')]),
  };
}

// peut être écrit comme :

function MyComponent() {
  return {
    view: () => (
      <main>
        <h1>Hello world</h1>
      </main>
    ),
  };
}

Lorsque vous utilisez JSX, vous pouvez interpoler des expressions JavaScript dans les balises JSX en utilisant des accolades :

jsx
var greeting = 'Hello';
var url = 'https://google.com';
var link = <a href={url}>{greeting}!</a>;
// donne <a href="https://google.com">Hello!</a>

Les composants peuvent être utilisés en respectant la convention de nommage qui consiste à mettre en majuscule la première lettre du nom du composant, ou en y accédant en tant que propriété :

jsx
m.render(document.body, <MyComponent />)
// équivalent à m.render(document.body, m(MyComponent))
<m.route.Link href="/home">Go home</m.route.Link>
// équivalent à m(m.route.Link, {href: "/home"}, "Go home")

Configuration ​

La manière la plus simple d'utiliser JSX est d'utiliser un plugin Babel.

Babel requiert npm, qui est automatiquement installé lorsque vous installez Node.js. Après avoir installé npm, créez un dossier de projet et exécutez cette commande :

bash
npm init -y

Si vous souhaitez utiliser Webpack et Babel ensemble, consultez la section ci-dessous.

Pour installer Babel en tant qu'outil autonome, utilisez cette commande :

bash
npm install @babel/core @babel/cli @babel/preset-env @babel/plugin-transform-react-jsx --save-dev

Créez un fichier .babelrc :

json
{
  "presets": ["@babel/preset-env"],
  "plugins": [
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "m",
        "pragmaFrag": "'['"
      }
    ]
  ]
}

Pour exécuter Babel, vous devez configurer un script npm. Ouvrez package.json et ajoutez cette entrée dans la section "scripts" :

json
{
  "name": "my-project",
  "scripts": {
    "babel": "babel src --out-dir bin --source-maps"
  }
}

Vous pouvez maintenant exécuter Babel en utilisant cette commande :

bash
npm run babel

Utilisation de Babel avec Webpack ​

Si vous n'avez pas encore installé Webpack comme bundler, utilisez la commande suivante :

bash
npm install webpack webpack-cli --save-dev

Vous pouvez intégrer Babel avec Webpack en suivant les étapes suivantes :

bash
npm install @babel/core babel-loader @babel/preset-env @babel/plugin-transform-react-jsx --save-dev

Créez un fichier .babelrc :

json
{
  "presets": ["@babel/preset-env"],
  "plugins": [
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "m",
        "pragmaFrag": "'['"
      }
    ]
  ]
}

Ensuite, créez un fichier nommé webpack.config.js :

jsx
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, './bin'),
    filename: 'app.js',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /\/node_modules\//,
        use: {
          loader: 'babel-loader',
        },
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

Si vous connaissez déjà Webpack, notez que l'ajout des options Babel à la section babel-loader de votre fichier webpack.config.js provoquera une erreur. Vous devez donc les inclure dans un fichier .babelrc distinct.

Cette configuration suppose que le fichier de code source pour le point d'entrée de l'application se trouve dans src/index.js, et qu'elle générera le bundle dans bin/app.js.

Pour exécuter le bundler, configurez un script npm. Ouvrez package.json et ajoutez cette entrée dans la section "scripts" :

json
{
  "name": "my-project",
  "scripts": {
    "start": "webpack --mode development --watch"
  }
}

Vous pouvez maintenant exécuter le bundler en lançant cette commande depuis la ligne de commande :

bash
npm start

Compilation pour la production ​

Pour générer un fichier minifié, ouvrez package.json et ajoutez un nouveau script npm nommé build :

json
{
  "name": "my-project",
  "scripts": {
    "start": "webpack -d --watch",
    "build": "webpack -p"
  }
}

Vous pouvez utiliser des hooks dans votre environnement de production afin d'exécuter automatiquement le script de construction de production. Voici un exemple pour Heroku :

json
{
  "name": "my-project",
  "scripts": {
    "start": "webpack -d --watch",
    "build": "webpack -p",
    "heroku-postbuild": "webpack -p"
  }
}

Rendre m accessible globalement ​

Pour accéder à m globalement depuis l'ensemble de votre projet, commencez par importer webpack dans votre fichier webpack.config.js comme ceci :

js
const webpack = require('webpack');

Ensuite, créez un nouveau plugin dans la propriété plugins de l'objet de configuration Webpack :

js
{
  plugins: [
    new webpack.ProvidePlugin({
      m: 'mithril',
    }),
  ];
}

Consultez la documentation Webpack pour plus d'informations sur ProvidePlugin.

Différences avec React ​

JSX dans Mithril présente des différences subtiles mais importantes par rapport au JSX de React.

Conventions de casse pour les propriétés d'attribut et de style ​

React exige que vous utilisiez les noms de propriétés DOM en camelCase au lieu des noms d'attributs HTML, sauf pour les attributs data-* et aria-*. Par exemple, en utilisant className au lieu de class et htmlFor au lieu de for. Dans Mithril, il est plus courant d'utiliser les noms d'attributs HTML en minuscules à la place. Mithril essaie toujours de définir les attributs si une propriété n'existe pas, ce qui correspond plus intuitivement au HTML. Notez que dans la plupart des cas, les noms de propriétés DOM et les noms d'attributs HTML sont soit identiques, soit très similaires. Par exemple, value/checked pour les entrées et l'attribut global tabindex par rapport à la propriété elem.tabIndex sur les éléments HTML. Il est très rare qu'ils diffèrent au-delà de la casse : la propriété elem.className pour l'attribut class ou la propriété elem.htmlFor pour l'attribut for font partie des rares exceptions.

De même, React utilise toujours les noms de propriétés de style en camelCase exposés dans le DOM via les propriétés de elem.style (comme cssHeight et backgroundColor). Mithril prend en charge à la fois cela et les noms de propriétés CSS en kebab-case (comme height et background-color) et préfère idiomatiquement ces derniers. Seuls cssHeight, cssFloat et les propriétés avec préfixes de fournisseur diffèrent de plus que la casse.

Événements DOM ​

React met en majuscule le premier caractère de tous les gestionnaires d'événements : onClick écoute les événements click et onSubmit les événements submit. Certains sont en outre modifiés car il s'agit de plusieurs mots concaténés ensemble. Par exemple, onMouseMove écoute les événements mousemove. Mithril n'effectue pas cette conversion de casse, mais ajoute simplement le préfixe on à l'événement natif. Vous ajouteriez donc des écouteurs pour onclick et onmousemove pour écouter ces deux événements respectivement. Cela correspond beaucoup plus étroitement au schéma de nommage de HTML et est beaucoup plus intuitif si vous venez d'un environnement HTML ou DOM pur.

React prend en charge la planification des écouteurs d'événements pendant la phase de capture (au premier passage, de l'extérieur vers l'intérieur, par opposition à la phase de bubbling par défaut allant de l'intérieur vers l'extérieur au deuxième passage) en ajoutant Capture à cet événement. Mithril ne dispose actuellement pas d'une telle fonctionnalité, mais il pourrait l'acquérir à l'avenir. Si cela est nécessaire, vous pouvez ajouter et supprimer manuellement vos propres écouteurs dans les hooks de cycle de vie.

JSX vs hyperscript ​

JSX et hyperscript sont deux syntaxes différentes que vous pouvez utiliser pour spécifier des vnodes, et elles ont des avantages et des inconvénients différents :

  • JSX est plus facile à adopter si vous venez d'un environnement HTML/XML et que vous êtes plus à l'aise pour spécifier des éléments DOM avec ce type de syntaxe. Il est aussi souvent plus lisible dans de nombreux cas, car il utilise moins de ponctuation et les attributs sont moins chargés visuellement, de sorte que de nombreuses personnes le trouvent beaucoup plus facile à lire. Et bien sûr, de nombreux éditeurs courants offrent une prise en charge de l'autocomplétion pour les éléments DOM de la même manière qu'ils le font pour HTML. Cependant, il nécessite une étape de build supplémentaire pour être utilisé, la prise en charge par les éditeurs n'est pas aussi étendue qu'avec du JS standard, et il est considérablement plus verbeux. Il est également un peu plus verbeux lorsqu'il s'agit de beaucoup de contenu dynamique, car vous devez utiliser des interpolations pour tout.

  • Hyperscript est plus facile à adopter si vous venez d'un environnement JS backend qui n'implique pas beaucoup de HTML ou de XML. Il est plus concis avec moins de redondance, et il fournit un sucre de syntaxe de type CSS pour les classes statiques, les ID et autres attributs. Il peut également être utilisé sans aucune étape de build, bien que vous puissiez en ajouter une si vous le souhaitez. Et il est légèrement plus facile de travailler avec lui face à beaucoup de contenu dynamique, car vous n'avez pas besoin d'"interpoler" quoi que ce soit. Cependant, cette concision le rend plus difficile à lire pour certaines personnes, en particulier celles qui sont moins expérimentées et qui viennent d'un arrière-plan HTML/CSS/XML. Je ne connais aucun plugin qui auto-complète des parties de sélecteurs hyperscript comme les ID, les classes et les attributs.

Vous pouvez observer les avantages et les inconvénients dans des arborescences plus complexes. Par exemple, considérez cette arborescence hyperscript, adaptée d'un projet réel par @dead-claudia avec quelques modifications pour plus de clarté et de lisibilité :

javascript
function SummaryView() {
  let tag, posts;

  function init({ attrs }) {
    Model.sendView(attrs.tag != null);
    if (attrs.tag != null) {
      tag = attrs.tag.toLowerCase();
      posts = Model.getTag(tag);
    } else {
      tag = undefined;
      posts = Model.posts;
    }
  }

  function feed(type, href) {
    return m('.feed', [
      type,
      m('a', { href }, m('img.feed-icon[src=./feed-icon-16.gif]')),
    ]);
  }

  return {
    oninit: init,
    // To ensure the tag gets properly diffed on route change.
    onbeforeupdate: init,
    view: () =>
      m('.blog-summary', [
        m('p', 'My ramblings about everything'),

        m('.feeds', [
          feed('Atom', 'blog.atom.xml'),
          feed('RSS', 'blog.rss.xml'),
        ]),

        tag != null
          ? m(TagHeader, { len: posts.length, tag })
          : m('.summary-header', [
              m('.summary-title', 'Posts, sorted by most recent.'),
              m(TagSearch),
            ]),

        m(
          '.blog-list',
          posts.map(post =>
            m(
              m.route.Link,
              {
                class: 'blog-entry',
                href: `/posts/${post.url}`,
              },
              [
                m(
                  '.post-date',
                  post.date.toLocaleDateString('en-US', {
                    year: 'numeric',
                    month: 'long',
                    day: 'numeric',
                  })
                ),

                m('.post-stub', [
                  m('.post-title', post.title),
                  m('.post-preview', post.preview, '...'),
                ]),

                m(TagList, { post, tag }),
              ]
            )
          )
        ),
      ]),
  };
}

Voici l'équivalent exact du code ci-dessus, en utilisant JSX à la place. Vous pouvez voir comment les deux syntaxes diffèrent juste dans ce bit, et quels avantages et inconvénients s'appliquent.

jsx
function SummaryView() {
  let tag, posts;

  function init({ attrs }) {
    Model.sendView(attrs.tag != null);
    if (attrs.tag != null) {
      tag = attrs.tag.toLowerCase();
      posts = Model.getTag(tag);
    } else {
      tag = undefined;
      posts = Model.posts;
    }
  }

  function feed(type, href) {
    return (
      <div class="feed">
        {type}
        <a href={href}>
          <img class="feed-icon" src="./feed-icon-16.gif" />
        </a>
      </div>
    );
  }

  return {
    oninit: init,
    // To ensure the tag gets properly diffed on route change.
    onbeforeupdate: init,
    view: () => (
      <div class="blog-summary">
        <p>My ramblings about everything</p>

        <div class="feeds">
          {feed('Atom', 'blog.atom.xml')}
          {feed('RSS', 'blog.rss.xml')}
        </div>

        {tag != null ? (
          <TagHeader len={posts.length} tag={tag} />
        ) : (
          <div class="summary-header">
            <div class="summary-title">Posts, sorted by most recent</div>
            <TagSearch />
          </div>
        )}

        <div class="blog-list">
          {posts.map(post => (
            <m.route.Link class="blog-entry" href={`/posts/${post.url}`}>
              <div class="post-date">
                {post.date.toLocaleDateString('en-US', {
                  year: 'numeric',
                  month: 'long',
                  day: 'numeric',
                })}
              </div>

              <div class="post-stub">
                <div class="post-title">{post.title}</div>
                <div class="post-preview">{post.preview}...</div>
              </div>

              <TagList post={post} tag={tag} />
            </m.route.Link>
          ))}
        </div>
      </div>
    ),
  };
}

Conseils et astuces ​

Conversion de HTML en JSX ​

Dans Mithril.js, le HTML bien formé est généralement un JSX valide. Il suffit généralement d'utiliser du HTML brut pour que les choses fonctionnent. Les seules choses que vous auriez normalement à faire sont de changer les valeurs de propriétés non guillemetées comme attr=value en attr="value" et de changer les éléments vides comme <input> en <input />, ceci étant dû au fait que JSX est basé sur XML et non sur HTML.

Pour accélérer ce processus, vous pouvez utiliser un convertisseur HTML vers modèle Mithril créé par la communauté pour faire une grande partie du travail pour vous.

Pager
Page précédenteApplication Simple
Page suivanteES6+ sur les navigateurs anciens

Publié sous la licence MIT.

Copyright (c) 2024 Mithril Contributors

https://mithril.js.org/jsx.html

Publié sous la licence MIT.

Copyright (c) 2024 Mithril Contributors