Skip to content
Mithril.js 2
Main Navigation PrzewodnikAPI

Polski

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

Polski

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

Wygląd

Sidebar Navigation

Pierwsze kroki

Instalacja

Prosta aplikacja

Zasoby

JSX

ES6+ na starszych przeglądarkach

Animacje

Testowanie

Przykłady

Integracja z zewnętrznymi bibliotekami

Obsługa ścieżek

Kluczowe koncepcje

Węzły Virtual DOM

Komponenty

Metody cyklu życia

Klucze

System automatycznego odświeżania

Różne

Porównanie frameworków

Migracja z v1.x

Migracja z wersji 0.2.x

API

Na tej stronie

JSX ​

Opis JSX ​

JSX to rozszerzenie składni JavaScript, które pozwala na pisanie kodu przypominającego HTML wewnątrz plików JavaScript. Nie jest to wymagane do tworzenia aplikacji Mithril.js, ale może zwiększyć czytelność i ułatwić pisanie komponentów, w zależności od preferencji Twoich lub Twojego zespołu.

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

// Można to zapisać również tak:

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

Używając JSX, możesz wstawiać wyrażenia JavaScript wewnątrz tagów JSX za pomocą nawiasów klamrowych:

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

Komponenty mogą być używane poprzez zastosowanie konwencji pisania nazwy komponentu wielką literą lub poprzez dostęp do niego jako właściwości:

jsx
m.render(document.body, <MyComponent />)
// równoważne z m.render(document.body, m(MyComponent))
<m.route.Link href="/home">Go home</m.route.Link>
// równoważne z m(m.route.Link, {href: "/home"}, "Go home")

Konfiguracja ​

Najprostszym sposobem na używanie JSX jest użycie wtyczki Babel.

Babel wymaga npm, który jest instalowany automatycznie podczas instalacji Node.js. Po zainstalowaniu npm utwórz folder projektu i uruchom następujące polecenie:

bash
npm init -y

Jeśli chcesz używać Webpacka i Babel razem, przejdź do sekcji poniżej.

Aby zainstalować Babel jako samodzielne narzędzie, użyj tego polecenia:

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

Utwórz plik .babelrc:

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

Aby uruchomić Babel, skonfiguruj skrypt w npm. Otwórz plik package.json i dodaj następujący wpis w sekcji "scripts":

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

Możesz teraz uruchomić Babel za pomocą tego polecenia:

bash
npm run babel

Używanie Babel z Webpackiem ​

Jeśli nie masz jeszcze zainstalowanego Webpacka jako bundlera, użyj tego polecenia:

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

Aby zintegrować Babel z Webpackiem, wykonaj następujące kroki:

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

Utwórz plik .babelrc:

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

Następnie utwórz plik o nazwie 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'],
  },
};

Dla osób zaznajomionych z Webpackiem: dodanie opcji Babel do sekcji babel-loader w pliku webpack.config.js spowoduje błąd, dlatego należy dołączyć je w oddzielnym pliku .babelrc.

Ta konfiguracja zakłada, że plik kodu źródłowego dla punktu wejścia aplikacji znajduje się w src/index.js, a wygenerowany pakiet zostanie umieszczony w bin/app.js.

Aby uruchomić bundler, skonfiguruj skrypt w npm. Otwórz plik package.json i dodaj następujący wpis w sekcji "scripts":

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

Możesz teraz uruchomić bundler, uruchamiając następujące polecenie:

bash
npm start

Kompilacja produkcyjna ​

Aby wygenerować zminifikowany plik, otwórz package.json i dodaj nowy skrypt npm o nazwie build:

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

W środowisku produkcyjnym możesz użyć hooków, aby automatycznie uruchamiać skrypt kompilacji produkcyjnej. Oto przykład dla Heroku:

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

Udostępnianie m globalnie ​

Aby uzyskać dostęp do m globalnie w całym projekcie, najpierw zaimportuj webpack w swoim pliku webpack.config.js w następujący sposób:

js
const webpack = require('webpack');

Następnie utwórz nową wtyczkę w sekcji plugins obiektu konfiguracji Webpack:

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

Zobacz dokumentację Webpacka, aby uzyskać więcej informacji na temat ProvidePlugin.

Różnice w porównaniu do React ​

JSX w Mithril.js ma subtelne, ale istotne różnice w porównaniu do JSX w React.

Konwencje dotyczące wielkości liter atrybutów i właściwości stylów ​

W React wymagane są nazwy właściwości DOM (zapisywane notacją camelCase) zamiast nazw atrybutów HTML, z wyjątkiem atrybutów data-* i aria-*. Na przykład, użycie className zamiast class i htmlFor zamiast for. W Mithril.js zaleca się używanie nazw atrybutów HTML pisanych małymi literami. Mithril.js zawsze próbuje ustawić atrybut, jeśli właściwość nie istnieje, co jest bardziej intuicyjne w odniesieniu do HTML. Należy zauważyć, że w większości przypadków nazwy właściwości DOM i atrybutów HTML są takie same lub bardzo podobne. Na przykład value/checked dla pól wejściowych i atrybut globalny tabindex w porównaniu z właściwością elem.tabIndex na elementach HTML. Bardzo rzadko różnią się one czymś więcej niż wielkością liter: właściwość elem.className dla atrybutu class lub właściwość elem.htmlFor dla atrybutu for należą do nielicznych wyjątków.

Podobnie, React zawsze używa nazw właściwości stylów pisanych notacją camelCase, udostępnianych w DOM za pośrednictwem właściwości elem.style (takich jak cssHeight i backgroundColor). Mithril.js obsługuje zarówno ten sposób, jak i nazwy właściwości CSS pisane kebab-case (takie jak height i background-color) i preferuje te drugie. Tylko cssHeight, cssFloat i właściwości z prefiksem dostawcy różnią się czymś więcej niż wielkością liter.

Zdarzenia DOM ​

W React pierwszy znak w nazwach obsługi zdarzeń jest pisany wielką literą: onClick obsługuje zdarzenia click, a onSubmit zdarzenia submit. Niektóre są dodatkowo zmieniane, ponieważ są to wielokrotne słowa połączone ze sobą. Na przykład onMouseMove obsługuje zdarzenia mousemove. Mithril.js nie wykonuje tego mapowania wielkości liter, ale zamiast tego po prostu dodaje on do nazwy natywnego zdarzenia, więc dodajesz nasłuchiwacze dla onclick i onmousemove, aby nasłuchiwać odpowiednio tych dwóch zdarzeń. Odpowiada to znacznie ściślej schematowi nazewnictwa HTML i jest bardziej intuicyjne, jeśli masz doświadczenie w HTML lub vanilla DOM.

React obsługuje planowanie nasłuchiwaczy zdarzeń podczas fazy przechwytywania (w pierwszym przebiegu, od zewnątrz do wewnątrz, w przeciwieństwie do domyślnej fazy bąbelkowania, przechodzącej od wewnątrz na zewnątrz w drugim przebiegu), dodając Capture do nazwy zdarzenia. Mithril.js obecnie nie ma takiej funkcjonalności, ale może ją zyskać w przyszłości. Jeśli jest to konieczne, możesz ręcznie dodawać i usuwać własne nasłuchiwacze w hookach cyklu życia.

JSX vs hyperscript ​

JSX i hyperscript to dwie różne składnie, których można użyć do definiowania vnode'ów i mają one różne zalety i wady:

  • Jeśli znasz HTML/XML, JSX będzie bardziej przystępny, ponieważ pozwala na definiowanie elementów DOM za pomocą podobnej składni. Jest również nieco czystszy w wielu przypadkach, ponieważ używa mniej interpunkcji, a atrybuty zawierają mniej szumu wizualnego, więc wielu osobom wydaje się znacznie łatwiejszy do odczytania. Wiele popularnych edytorów zapewnia obsługę autouzupełniania dla elementów DOM w taki sam sposób, jak w przypadku HTML. Wymaga jednak dodatkowego kroku kompilacji, aby go użyć, obsługa edytora nie jest tak szeroka, jak w przypadku normalnego JS, i jest nieco bardziej rozwlekły. Jest również nieco bardziej rozwlekły, gdy masz do czynienia z dużą ilością dynamicznej zawartości, ponieważ musisz używać interpolacji do wszystkiego.

  • Jeśli masz doświadczenie w backendzie JS i nie znasz dobrze HTML/XML, hyperscript może być dla Ciebie bardziej przystępny. Jest bardziej zwięzły z mniejszą redundancją i zapewnia cukier składniowy podobny do CSS dla statycznych klas, identyfikatorów i innych atrybutów. Można go również używać bez żadnego kroku kompilacji, chociaż możesz dodać jeden, jeśli chcesz. Jest nieco łatwiejszy w pracy w obliczu dużej ilości dynamicznej zawartości, ponieważ nie musisz niczego "interpolować". Jednak zwięzłość utrudnia czytanie niektórym osobom, zwłaszcza tym mniej doświadczonym i pochodzącym z front-endowego tła HTML/CSS/XML, i nie znam żadnych wtyczek, które automatycznie uzupełniają części selektorów hyperscript, takie jak identyfikatory, klasy i atrybuty.

Możesz zobaczyć, jak te zalety i wady wpływają na bardziej złożone drzewa. Na przykład, rozważ to drzewo hyperscript, zaadaptowane z rzeczywistego projektu przez @dead-claudia z pewnymi zmianami dla jasności i czytelności:

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

Oto dokładny odpowiednik powyższego kodu, używający zamiast tego JSX. Możesz zobaczyć, jak te dwie składnie różnią się tylko w tym fragmencie kodu i jakie zalety i wady mają zastosowanie.

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

Porady i triki ​

Konwertowanie HTML na JSX ​

W Mithril.js poprawnie sformatowany HTML jest zazwyczaj poprawnym JSX. Zazwyczaj wystarczy zmienić wartości atrybutów bez cudzysłowów (np. attr=value na attr="value") oraz zamknąć tagi elementów bez zawartości (np. <input> na <input />), ponieważ JSX bazuje na XML, a nie na HTML.

Używając hyperscript, często musisz przetłumaczyć HTML na składnię hyperscript, aby go użyć. Aby przyspieszyć ten proces, możesz użyć stworzonego przez społeczność konwertera HTML na szablony Mithril, aby zrobić to za Ciebie.

Pager
Poprzednia stronaProsta aplikacja
Następna stronaES6+ na starszych przeglądarkach

Opublikowano na licencji MIT.

Copyright (c) 2024 Mithril Contributors

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

Opublikowano na licencji MIT.

Copyright (c) 2024 Mithril Contributors