Skip to content
Mithril.js 2
Main Navigation NávodAPI

čeština

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

čeština

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

Vzhled

Sidebar Navigation

Začínáme

Instalace

Jednoduchá aplikace

Zdroje

JSX

ES6+ na starších prohlížečích

Animace

Testování

Příklady

Integrace s knihovnami třetích stran

Zpracování cest

Klíčové koncepty

Virtuální DOM uzly

Komponenty

Metody životního cyklu

Klíče (Keys)

Systém automatického překreslování (redraw)

Různé

Srovnání frameworků

Migrace z v1.x

Migrace z verze 0.2.x

API

Na této stránce

JSX ​

Popis ​

JSX je syntaktické rozšíření JavaScriptu, které umožňuje psát HTML tagy přímo v JavaScriptovém kódu. Není součástí standardu JavaScriptu a pro vytváření aplikací není nutné ho používat, ale pro vás nebo váš tým může být jeho použití příjemnější.

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

// lze zapsat jako:

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

Při použití JSX lze do tagů vkládat JavaScriptové výrazy pomocí složených závorek:

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

Komponenty lze použít pomocí konvence velkého počátečního písmene názvu komponenty nebo přístupem k ní jako k vlastnosti:

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

Nastavení ​

Pro používání JSX je nejjednodušší použít plugin Babel.

Pro Babel je vyžadován npm, který se instaluje automaticky s Node.js. Po instalaci npm vytvořte složku projektu a spusťte tento příkaz:

bash
npm init -y

Pokud chcete používat Webpack a Babel společně, přejděte do sekce níže.

Chcete-li nainstalovat Babel jako samostatný nástroj, použijte tento příkaz:

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

Vytvořte soubor .babelrc:

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

Chcete-li spustit Babel, nastavte npm skript. Otevřete package.json a přidejte tento záznam do sekce "scripts":

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

Nyní můžete spustit Babel pomocí tohoto příkazu:

bash
npm run babel

Použití Babel s Webpack ​

Pokud jste ještě nenainstalovali Webpack jako bundler, použijte tento příkaz:

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

Babel můžete integrovat do Webpacku následujícími kroky:

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

Vytvořte soubor .babelrc:

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

Dále vytvořte soubor s názvem 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'],
  },
};

Pokud již Webpack znáte, pamatujte, že přidání Babel možností přímo do sekce babel-loader v webpack.config.js způsobí chybu. Proto je nutné je definovat v samostatném souboru .babelrc.

Tato konfigurace předpokládá, že zdrojový kód pro vstupní bod aplikace je v src/index.js a výstupní balíček bude uložen do bin/app.js.

Chcete-li spustit bundler, nastavte npm skript. Otevřete package.json a přidejte tento záznam do sekce "scripts":

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

Nyní můžete spustit bundler spuštěním tohoto příkazu z příkazové řádky:

bash
npm start

Produkční build ​

Chcete-li vygenerovat minimalizovaný soubor, otevřete package.json a přidejte nový npm skript s názvem build:

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

Můžete použít hooks ve vašem produkčním prostředí ke spuštění produkčního build skriptu automaticky. Zde je příklad pro použití na Heroku:

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

Zpřístupnění m globálně ​

Aby bylo možné přistupovat k m globálně z celého vašeho projektu, nejprve importujte webpack do vašeho webpack.config.js takto:

js
const webpack = require('webpack');

Poté vytvořte nový plugin ve vlastnosti plugins konfiguračního objektu Webpack:

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

Další informace o ProvidePlugin najdete v dokumentaci Webpack.

Rozdíly oproti React ​

JSX v Mithril se v některých jemných, ale důležitých aspektech liší od JSX v React.

Konvence pro psaní velkých a malých písmen u atributů a vlastností stylu ​

React vyžaduje používání camelCase notace pro názvy DOM vlastností namísto HTML atributů, s výjimkou atributů data-* a aria-*. Například použití className místo class a htmlFor místo for. V Mithril se obvykle používají názvy HTML atributů psané malými písmeny. Mithril se vždy pokusí nastavit atribut, pokud vlastnost neexistuje, což je intuitivnější s HTML. Většinou jsou názvy vlastností DOM a HTML atributů buď stejné, nebo velmi podobné. Například value/checked pro vstupy a globální atribut tabindex vs. vlastnost elem.tabIndex na HTML elementech. Velmi zřídka se liší více než v psaní velkých a malých písmen: vlastnost elem.className pro atribut class nebo vlastnost elem.htmlFor pro atribut for patří mezi několik výjimek.

Podobně React vždy používá názvy vlastností stylu psané camelCase, které jsou zpřístupněny v DOM prostřednictvím vlastností elem.style (jako cssHeight a backgroundColor). Mithril podporuje jak camelCase, tak názvy CSS vlastností psané kebab-case (jako height a background-color) a idiomaticky preferuje kebab-case. Pouze cssHeight, cssFloat a vlastnosti s prefixem dodavatele se liší ve více než v psaní velkých a malých písmen.

DOM události ​

React používá velká písmena pro první znak v názvech obslužných rutin událostí: onClick pro událost click, onSubmit pro událost submit. Některé jsou dále upraveny, protože se jedná o více slov spojených dohromady. Například onMouseMove naslouchá událostem mousemove. Mithril toto mapování nepoužívá. Místo toho jednoduše přidává předponu on k názvu nativní události. Pro události click a mousemove byste tedy použili posluchače onclick a onmousemove. To mnohem více odpovídá schématu pojmenování HTML a je intuitivnější, pokud pocházíte z HTML nebo vanilla DOM prostředí.

React podporuje plánování posluchačů událostí během fáze zachycení (v prvním průchodu, zvenku dovnitř, na rozdíl od výchozí fáze bublání jdoucí dovnitř ven ve druhém průchodu) připojením Capture k dané události. Mithril v současné době takovou funkčnost postrádá, ale v budoucnu by ji mohl získat. Pokud je to nutné, můžete ručně přidávat a odebírat vlastní posluchače v lifecycle hooks.

JSX vs hyperscript ​

JSX a hyperscript jsou dvě různé syntaxe pro definování vnode (virtuálních uzlů) a každá má své výhody a nevýhody:

  • JSX je přístupnější, pokud máte zkušenosti s HTML/XML a je vám pohodlnější specifikovat DOM elementy s tímto druhem syntaxe. V mnoha případech je také přehlednější, protože používá méně interpunkce a atributy jsou méně vizuálně rušivé, což usnadňuje čtení. A samozřejmě, mnoho běžných editorů poskytuje podporu automatického doplňování pro DOM elementy stejným způsobem, jako to dělají pro HTML. Vyžaduje však další krok sestavení, podpora editorů není tak široká jako u normálního JS a je výrazně více rozvláčný. Při práci s velkým množstvím dynamického obsahu může být také poněkud zdlouhavější, protože vyžaduje interpolaci pro všechny dynamické hodnoty.

  • Hyperscript je přístupnější, pokud máte zkušenosti s backendovým JS prostředím, které nezahrnuje mnoho HTML nebo XML. Je stručnější s menší redundancí a poskytuje cukr podobný CSS pro statické třídy, ID a další atributy. Lze jej také použít bez jakéhokoli kroku sestavení, ačkoli můžete jeden přidat, pokud si přejete. A je o něco snazší s ním pracovat při práci s velkým množstvím dynamického obsahu, protože nemusíte nic "interpolovat". Pro některé uživatele, zejména pro ty s menšími zkušenostmi s front-end vývojem (HTML/CSS/XML), může být stručnost hyperscriptu hůře čitelná. Navíc nevím o žádných pluginech, které by automaticky doplňovaly části hyperscript selektorů, jako jsou ID, třídy a atributy.

Můžete vidět, jak se kompromisy projevují ve složitějších stromech. Například zvažte tento hyperscript strom, adaptovaný ze skutečného projektu od @dead-claudia s některými úpravami pro jasnost a čitelnost:

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

Zde je přesný ekvivalent výše uvedeného kódu pomocí JSX. Můžete vidět, jak se obě syntaxe liší a jaké kompromisy platí.

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

Tipy a triky ​

Převod HTML na JSX ​

V Mithril.js je dobře formátované HTML obecně platné JSX. Obvykle stačí jen vložit nezpracované HTML a vše by mělo fungovat. Jediné věci, které byste obvykle museli upravit, jsou hodnoty vlastností bez uvozovek, jako je attr=value, na attr="value" a změnit prázdné elementy jako <input> na <input />, což je způsobeno tím, že JSX je založeno na XML a ne na HTML.

Při použití hyperscriptu často potřebujete převést HTML na syntaxi hyperscriptu, abyste jej mohli použít. Chcete-li tento proces urychlit, můžete použít komunitní nástroj pro převod HTML do šablon Mithril, který automatizuje většinu konverze.

Pager
Předchozí stránkaJednoduchá aplikace
Další stránkaES6+ na starších prohlížečích

Vydáno pod licencí MIT.

Copyright (c) 2024 Mithril Contributors

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

Vydáno pod licencí MIT.

Copyright (c) 2024 Mithril Contributors