Skip to content
Mithril.js 2
Main Navigation GuíaAPI

Español

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

Español

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

Apariencia

Sidebar Navigation

Primeros pasos

Instalación

Aplicación sencilla

Recursos

JSX

ES6+ en navegadores antiguos

Animaciones

Pruebas

Ejemplos

Integración con terceros

Manejo de Rutas

Conceptos clave

Nodos del DOM virtual

Componentes

Métodos de ciclo de vida

Claves

El sistema de redibujado automático

Varios

Comparación de frameworks

Migrando desde v1.x

Migración desde v0.2.x

API

En esta página

JSX ​

Descripción ​

JSX es una extensión de sintaxis que permite escribir etiquetas HTML intercaladas con JavaScript. No forma parte de ningún estándar de JavaScript y no es imprescindible para construir aplicaciones, pero su uso puede resultar más agradable según tus preferencias o las de tu equipo.

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

// puede escribirse como:

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

Cuando se usa JSX, es posible interpolar expresiones de JavaScript dentro de las etiquetas JSX usando llaves:

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

Los componentes se pueden utilizar siguiendo una convención que consiste en poner en mayúscula la primera letra del nombre del componente o accediendo a él como una propiedad:

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

Configuración ​

La manera más sencilla de usar JSX es mediante un plugin de Babel.

Babel requiere npm, que se instala automáticamente cuando instalas Node.js. Una vez que npm esté instalado, crea una carpeta de proyecto y ejecuta este comando:

bash
npm init -y

Si deseas usar Webpack y Babel juntos, salta a la sección siguiente.

Para instalar Babel como una herramienta independiente, usa este comando:

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

Crea un archivo llamado .babelrc:

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

Para ejecutar Babel, configura un script de npm. Abre package.json y añade esta entrada bajo "scripts":

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

Ahora puedes ejecutar Babel usando este comando:

bash
npm run babel

Usando Babel con Webpack ​

Si aún no has instalado Webpack como empaquetador (bundler), usa este comando:

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

Puedes integrar Babel con Webpack siguiendo estos pasos:

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

Crea un archivo llamado .babelrc:

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

Luego, crea un archivo llamado 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'],
  },
};

Para aquellos que ya estén familiarizados con Webpack, tengan en cuenta que agregar las opciones de Babel a la sección babel-loader de su webpack.config.js generará un error, por lo que es necesario incluirlas en el archivo .babelrc por separado.

Esta configuración asume que el archivo de código fuente para el punto de entrada de la aplicación está en src/index.js, y esto generará el bundle en bin/app.js.

Para ejecutar el empaquetador, configura un script de npm. Abre package.json y añade esta entrada bajo "scripts":

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

Ahora puedes ejecutar el empaquetador ejecutando esto desde la línea de comandos:

bash
npm start

Compilación para producción ​

Para generar un archivo minificado, abre package.json y añade un nuevo script de npm llamado build:

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

Puedes usar hooks en tu entorno de producción para ejecutar automáticamente el script de build de producción. Aquí hay un ejemplo para Heroku:

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

Haciendo que m sea accesible globalmente ​

Para poder acceder a m globalmente desde todo tu proyecto, primero importa webpack en tu archivo webpack.config.js de esta manera:

js
const webpack = require('webpack');

Luego crea un nuevo plugin en la propiedad plugins del objeto de configuración de Webpack:

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

Consulta la documentación de Webpack para más información sobre ProvidePlugin.

Diferencias con React ​

JSX en Mithril presenta algunas diferencias sutiles pero importantes en comparación con el JSX de React.

Convenciones de mayúsculas y minúsculas para propiedades de atributos y estilos ​

React requiere que utilices los nombres de propiedad DOM en camelCase en lugar de los nombres de atributos HTML para todos los atributos que no sean data-* y aria-*. Por ejemplo, usar className en lugar de class y htmlFor en lugar de for. En Mithril, es más común usar los nombres de atributos HTML en minúsculas. Mithril siempre recurre a establecer atributos si una propiedad no existe, lo que se alinea más intuitivamente con HTML. Ten en cuenta que, en la mayoría de los casos, los nombres de propiedad DOM y los nombres de atributos HTML son iguales o muy similares. Por ejemplo, value/checked para las entradas y el atributo global tabindex frente a la propiedad elem.tabIndex en los elementos HTML. Muy raramente difieren más allá de las mayúsculas y minúsculas: la propiedad elem.className para el atributo class o la propiedad elem.htmlFor para el atributo for se encuentran entre las pocas excepciones.

De manera similar, React siempre utiliza los nombres de propiedad de estilo en camelCase expuestos en el DOM a través de las propiedades de elem.style (como cssHeight y backgroundColor). Mithril admite tanto eso como los nombres de propiedad CSS en kebab-case (como height y background-color), y prefiere idiomáticamente este último. Solo cssHeight, cssFloat y las propiedades con prefijo de proveedor difieren en algo más que en mayúsculas y minúsculas.

Eventos DOM ​

React convierte a mayúscula el primer carácter de todos los controladores de eventos: onClick escucha los eventos click y onSubmit escucha los eventos submit. Algunos se alteran aún más a medida que son varias palabras concatenadas. Por ejemplo, onMouseMove escucha los eventos mousemove. Mithril no realiza esta conversión de mayúsculas y minúsculas, sino que simplemente añade el prefijo on al evento nativo, por lo que añadirías listeners para onclick y onmousemove para escuchar esos dos eventos respectivamente. Esto corresponde mucho más estrechamente al esquema de nombres de HTML y es mucho más intuitivo si provienes de un entorno de HTML o DOM vainilla.

React admite la programación de listeners de eventos durante la fase de captura (en la primera pasada, de afuera hacia adentro, en contraposición a la fase de burbuja predeterminada que va de adentro hacia afuera en la segunda pasada) añadiendo Capture a ese evento. Mithril actualmente carece de tal funcionalidad, pero podría ganarla en el futuro. Si esto es necesario, puedes agregar y eliminar manualmente tus propios listeners en lifecycle hooks.

JSX vs hyperscript ​

JSX e hyperscript son dos sintaxis diferentes que puedes usar para especificar vnodes, y tienen diferentes ventajas y desventajas:

  • JSX es mucho más accesible si provienes de un entorno de HTML/XML y te sientes más cómodo especificando elementos DOM con ese tipo de sintaxis. También suele ser más limpio, ya que utiliza menos signos de puntuación y los atributos contienen menos ruido visual, por lo que muchas personas lo encuentran más fácil de leer. Y, por supuesto, muchos editores comunes brindan soporte de autocompletado para elementos DOM de la misma manera que lo hacen para HTML. Sin embargo, requiere un paso de build adicional para usarlo, el soporte del editor no es tan amplio como con JS normal, y es considerablemente más detallado. También es un poco más detallado cuando se trata de mucho contenido dinámico porque tienes que usar interpolaciones para todo.

  • Hyperscript es más accesible si provienes de un entorno de JS backend que no involucra mucho HTML o XML. Es más conciso con menos redundancia, y proporciona un azúcar sintáctico similar a CSS para clases estáticas, ID y otros atributos. También se puede usar sin ningún paso de compilación, aunque puedes agregar uno si lo deseas. Y es un poco más fácil de trabajar al manejar una gran cantidad de contenido dinámico, porque no necesitas "interpolar" nada. Sin embargo, la brevedad puede dificultar la lectura para algunas personas, especialmente para aquellas con menos experiencia que provienen de un entorno de HTML/CSS/XML frontend, y no conozco ningún plugin que complete automáticamente partes de selectores de hyperscript como ID, clases y atributos.

Puedes observar las ventajas y desventajas en árboles más complejos. Por ejemplo, considera este árbol de hyperscript, adaptado de un proyecto del mundo real por @dead-claudia con algunas alteraciones para mayor claridad y legibilidad:

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

Aquí tienes el equivalente exacto del código anterior, utilizando JSX en su lugar. Puedes ver cómo las dos sintaxis difieren solo en este fragmento, y qué ventajas y desventajas se aplican.

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

Consejos y trucos ​

Convirtiendo HTML a JSX ​

En Mithril.js, el HTML bien formado generalmente es JSX válido. Se requiere poco más que simplemente pegar HTML sin formato para que las cosas funcionen. Casi lo único que normalmente tendrías que hacer es cambiar los valores de propiedad sin comillas, como attr=value, a attr="value", y cambiar los elementos vacíos, como <input>, a <input />, ya que JSX se basa en XML y no en HTML.

Cuando se usa hyperscript, a menudo necesitas traducir HTML a la sintaxis de hyperscript para usarlo. Para ayudar a acelerar este proceso, puedes usar un convertidor de HTML a plantilla de Mithril creado por la comunidad que hará gran parte del trabajo por ti.

Pager
AnteriorAplicación sencilla
SiguienteES6+ en navegadores antiguos

Publicado bajo la licencia MIT.

Copyright (c) 2024 Mithril Contributors

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

Publicado bajo la licencia MIT.

Copyright (c) 2024 Mithril Contributors