Skip to content
Mithril.js 2
Main Navigation GuiaAPI

Português – Brasil

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

Português – Brasil

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

Aparência

Sidebar Navigation

Começando

Instalação

Aplicativo Simples

Recursos

JSX

ES6+ em navegadores legados

Animações

Testes

Exemplos

Integração com Bibliotecas de Terceiros

Tratamento de Caminhos (Path Handling)

Conceitos-chave

Nós da DOM Virtual

Componentes

Métodos de ciclo de vida

Keys

O sistema de redesenho automático

Diversos

Comparação de Frameworks

Migrando da v1.x

Migração da v0.2.x

API

Nesta página

JSX ​

Descrição ​

JSX é uma extensão de sintaxe que permite escrever tags HTML misturadas com JavaScript. Não faz parte de nenhum padrão JavaScript e não é obrigatória para construir aplicações, mas pode ser mais agradável de usar, dependendo das suas preferências ou das da sua equipe.

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

// pode ser escrito da seguinte forma:

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

Ao usar JSX, é possível inserir expressões JavaScript dentro de tags JSX usando chaves:

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

Componentes podem ser usados capitalizando a primeira letra do nome do componente ou acessando-o como uma propriedade:

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")

Configuração ​

A maneira mais simples de usar JSX é por meio de um plugin do Babel.

O Babel requer npm, que é instalado automaticamente quando você instala o Node.js. Após a instalação do npm, crie uma pasta para o seu projeto e execute o seguinte comando:

bash
npm init -y

Se você quiser usar Webpack e Babel juntos, pule para a seção abaixo.

Para instalar o Babel como uma ferramenta independente, use este comando:

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

Crie um arquivo .babelrc:

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

Para executar o Babel, configure um script npm. Abra package.json e adicione esta entrada em "scripts":

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

Agora você pode executar o Babel usando este comando:

bash
npm run babel

Usando Babel com Webpack ​

Caso ainda não tenha instalado o Webpack como um bundler, utilize o seguinte comando:

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

Você pode integrar o Babel ao Webpack seguindo estes passos:

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

Crie um arquivo .babelrc:

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

Em seguida, crie um arquivo chamado 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'],
  },
};

Usuários familiarizados com o Webpack devem notar que adicionar as opções do Babel diretamente na seção babel-loader do arquivo webpack.config.js resultará em um erro. Portanto, inclua-as no arquivo .babelrc.

Esta configuração assume que o arquivo de código-fonte para o ponto de entrada da aplicação está em src/index.js, e isso irá gerar o bundle para bin/app.js.

Para executar o bundler, configure um script npm. Abra package.json e adicione esta entrada em "scripts":

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

Agora você pode executar o bundler executando isto na linha de comando:

bash
npm start

Build de produção ​

Para gerar um arquivo minificado, abra package.json e adicione um novo script npm chamado build:

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

Você pode utilizar hooks no seu ambiente de produção para automatizar a execução do script de build. Aqui está um exemplo para Heroku:

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

Tornando m acessível globalmente ​

Para tornar m acessível globalmente em todo o seu projeto, importe webpack no arquivo webpack.config.js da seguinte forma:

js
const webpack = require('webpack');

Em seguida, crie um novo plugin na propriedade plugins do objeto de configuração do Webpack:

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

Consulte a documentação do Webpack para obter mais informações sobre ProvidePlugin.

Diferenças com React ​

O JSX no Mithril apresenta algumas diferenças sutis, porém importantes, em relação ao JSX do React.

Convenções de caixa de propriedades de atributo e estilo ​

O React exige que você use os nomes de propriedades DOM em camelCase em vez de nomes de atributos HTML para todos os atributos, exceto atributos data-* e aria-*. Por exemplo, usar className em vez de class e htmlFor em vez de for. No Mithril, é mais idiomático usar os nomes de atributos HTML em minúsculas. O Mithril sempre retorna à definição de atributos caso uma propriedade não exista, o que é mais intuitivo em relação ao HTML. Observe que, na maioria dos casos, os nomes de propriedades DOM e atributos HTML são iguais ou muito semelhantes. Por exemplo, value/checked para entradas e o atributo global tabindex versus a propriedade elem.tabIndex em elementos HTML. Raramente eles diferem além do caso: a propriedade elem.className para o atributo class ou a propriedade elem.htmlFor para o atributo for estão entre as poucas exceções.

Da mesma forma, o React sempre usa os nomes de propriedades de estilo em camelCase expostos no DOM por meio de propriedades de elem.style (como cssHeight e backgroundColor). O Mithril suporta tanto isso quanto os nomes de propriedades CSS em kebab-case (como height e background-color) e idiomáticamente prefere o último. Apenas cssHeight, cssFloat e propriedades com prefixo de fornecedor diferem em mais do que o caso.

Eventos DOM ​

No React, o primeiro caractere de todos os manipuladores de eventos é convertido para maiúsculo: onClick para eventos click e onSubmit para eventos submit. Alguns são ainda mais modificados por serem palavras concatenadas. Por exemplo, onMouseMove captura eventos mousemove. O Mithril não realiza essa conversão, apenas adiciona on ao evento nativo. Portanto, você adicionaria listeners para onclick e onmousemove para capturar os respectivos eventos. Essa abordagem se alinha mais ao esquema de nomenclatura do HTML e é mais intuitiva para quem tem experiência com HTML ou DOM vanilla.

O React suporta o agendamento de listeners de eventos durante a fase de captura (na primeira passagem, de fora para dentro, em oposição à fase de bolha padrão indo de dentro para fora na segunda passagem) anexando Capture a esse evento. O Mithril atualmente não possui tal funcionalidade, mas pode ganhar isso no futuro. Se isso for necessário, você pode adicionar e remover manualmente seus próprios listeners em hooks de ciclo de vida.

JSX vs hyperscript ​

JSX e hyperscript são duas sintaxes distintas para especificar vnodes, cada uma com suas vantagens e desvantagens.

  • JSX é muito mais acessível se você vem de um histórico de HTML/XML e está mais confortável em especificar elementos DOM com esse tipo de sintaxe. Também é um pouco mais limpo em muitos casos, pois usa menos pontuação e os atributos contêm menos ruído visual, então muitas pessoas acham muito mais fácil de ler. E, claro, muitos editores comuns fornecem suporte de autocompletar para elementos DOM da mesma forma que fazem para HTML. No entanto, requer uma etapa adicional de compilação para usar, o suporte nos editores não é tão amplo quanto com JS normal e é consideravelmente mais verboso. Também é um pouco mais verboso ao lidar com muito conteúdo dinâmico porque você tem que usar interpolações para tudo.

  • Hyperscript é mais adequado para desenvolvedores com experiência em JavaScript de backend, que não trabalham frequentemente com HTML ou XML. É mais conciso com menos redundância e fornece um atalho similar ao CSS para classes estáticas, IDs e outros atributos. Também pode ser usado sem nenhuma etapa de compilação, embora você possa adicionar uma se desejar. E é um pouco mais fácil de trabalhar ao lidar com muito conteúdo dinâmico, porque você não precisa "interpolar" nada. No entanto, a concisão torna mais difícil de ler para algumas pessoas, especialmente aquelas menos experientes e vindas de um histórico de front end HTML/CSS/XML, e não tenho conhecimento de nenhum plugin que preencha automaticamente partes de seletores hyperscript como IDs, classes e atributos.

As vantagens e desvantagens de cada sintaxe se tornam mais evidentes em estruturas mais complexas. Por exemplo, considere esta árvore hyperscript, adaptada de um projeto do mundo real por @dead-claudia com algumas alterações para clareza e legibilidade:

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

Aqui está o equivalente exato do código acima, usando JSX em vez disso. Você pode ver como as duas sintaxes diferem apenas neste bit e quais compensações se aplicam.

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

Dicas e truques ​

Convertendo HTML para JSX ​

Em Mithril.js, código HTML bem formatado geralmente é considerado JSX válido. Em muitos casos, basta colar o código HTML para que ele funcione. Quase as únicas coisas que você normalmente teria que fazer são alterar valores de propriedade não entre aspas como attr=value para attr="value" e alterar elementos vazios como <input> para <input />, isso devido ao JSX ser baseado em XML e não HTML.

Para agilizar a conversão, você pode utilizar um conversor de HTML para template Mithril, desenvolvido pela comunidade, que automatiza grande parte do processo.

Pager
AnteriorAplicativo Simples
PróximoES6+ em navegadores legados

Distribuído sob a Licença MIT.

Copyright (c) 2024 Mithril Contributors

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

Distribuído sob a Licença MIT.

Copyright (c) 2024 Mithril Contributors