Skip to content
Mithril.js 2
Main Navigation РуководствоAPI

Русский

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

Русский

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

Внешний вид

Sidebar Navigation

API

Основной API

m(selector, attributes, children)

render(element, vnodes)

mount(root, component)

route(root, defaultRoute, routes)

request(options)

parseQueryString(string)

buildQueryString(object)

buildPathname(object)

parsePathname(string)

trust(html)

fragment(attrs, children)

redraw()

censor(object, extra)

Опциональный API

stream()

Руководство

Содержание страницы

m(selector, attributes, children) ​

Описание ​

Создаёт HTML-элемент в view Mithril.js.

javascript
m('div.foo', { style: { color: 'red' } }, 'hello');
// рендерится в следующий HTML:
// <div class="foo" style="color: red">hello</div>

Вы также можете использовать HTML-подобный синтаксис, называемый JSX, используя Babel для преобразования его в эквивалентные вызовы hyperscript. Это эквивалентно примеру выше.

jsx
<div class="foo" style="color: red">
  hello
</div>

Сигнатура ​

vnode = m(selector, attrs, children)

АргументТипОбязательныйОписание
selectorString|Object|FunctionДаCSS-селектор или компонент
attrsObjectНетHTML-атрибуты или свойства элемента
childrenArray<Vnode>|String|Number|BooleanНетДочерние vnode. Может быть передан как splat arguments
возвращаемое значениеVnodeVnode

Как читать сигнатуры

Как это работает ​

Mithril.js предоставляет функцию hyperscript m(), которая позволяет описывать любую HTML-структуру с использованием синтаксиса JavaScript. Она принимает строку selector (обязательно), объект attrs (опционально) и массив children (опционально).

javascript
m('div', { id: 'box' }, 'hello');

// отображает этот HTML:
// <div id="box">hello</div>

Функция m() не возвращает напрямую DOM-элемент. Вместо этого она возвращает виртуальный DOM-узел, или vnode, который является объектом JavaScript, представляющим DOM-элемент, который необходимо создать.

javascript
// vnode
var vnode = {
  tag: 'div',
  attrs: { id: 'box' },
  children: [
    /*...*/
  ],
};

Чтобы преобразовать vnode в фактический DOM-элемент, используйте функцию m.render():

javascript
m.render(document.body, m('br')); // помещает <br> в <body>

Вызов m.render() несколько раз не приводит к воссозданию DOM-дерева с нуля при каждом вызове. Вместо этого, изменения в DOM вносятся только тогда, когда это необходимо для соответствия виртуальному DOM-дереву. Такое поведение предпочтительно, потому что воссоздание DOM с нуля является ресурсозатратным и вызывает такие проблемы, как потеря фокуса в полях ввода. В отличие от этого, обновление DOM только там, где это необходимо, значительно быстрее и упрощает поддержку сложных пользовательских интерфейсов, обрабатывающих множество пользовательских сценариев.

Гибкость ​

Функция m() является одновременно перегруженной и вариативной. Другими словами, она очень гибка в отношении принимаемых входных параметров:

javascript
// простой тег
m('div'); // <div></div>

// атрибуты и дочерние элементы необязательны
m('a', { id: 'b' }); // <a id="b"></a>
m('span', 'hello'); // <span>hello</span>

// тег с дочерними узлами
m('ul', [
  // <ul>
  m('li', 'hello'), //   <li>hello</li>
  m('li', 'world'), //   <li>world</li>
]); // </ul>

// массив необязателен
m(
  'ul', // <ul>
  m('li', 'hello'), //   <li>hello</li>
  m('li', 'world') //   <li>world</li>
); // </ul>

CSS-селекторы ​

Первым аргументом m() может быть любой CSS-селектор, описывающий HTML-элемент. Он принимает любые допустимые CSS-комбинации синтаксиса # (id), . (class) и [] (attribute).

javascript
m('div#hello');
// <div id="hello"></div>

m('section.container');
// <section class="container"></section>

m('input[type=text][placeholder=Name]');
// <input type="text" placeholder="Name" />

m("a#exit.external[href='https://example.com']", 'Leave');
// <a id="exit" class="external" href="https://example.com">Leave</a>

Если вы опустите имя тега, Mithril.js предполагает тег div.

javascript
m('.box.box-bordered'); // <div class="box box-bordered"></div>

Рекомендуется использовать CSS-селекторы для статических атрибутов (атрибутов с неизменяемыми значениями), а объект атрибутов - для динамических значений.

javascript
var currentURL = '/';

m(
  'a.link[href=/]',
  {
    class: currentURL === '/' ? 'selected' : '',
  },
  'Home'
);

// отображает этот HTML:
// <a href="/" class="link selected">Home</a>

Атрибуты, переданные в качестве второго аргумента ​

Вы можете передавать атрибуты, свойства, события и хуки жизненного цикла во втором, опциональном аргументе (подробности см. в следующих разделах).

JS
m("button", {
  class: "my-button",
  onclick: function() {/* ... */},
  oncreate: function() {/* ... */}
})

Если значение атрибута null или undefined, он игнорируется.

Если имена классов присутствуют как в первом, так и во втором аргументах m(), они объединяются вместе, как и ожидается. Если значение класса во втором аргументе равно null или undefined, оно игнорируется.

Если другой атрибут присутствует как в первом, так и во втором аргументе, второй имеет приоритет, даже если он равен null или undefined.

DOM-атрибуты ​

Mithril.js использует как JavaScript API, так и DOM API (setAttribute) для установки атрибутов. Это означает, что вы можете использовать оба синтаксиса для обращения к атрибутам.

Например, в JavaScript API атрибут readonly называется element.readOnly (обратите внимание на верхний регистр). В Mithril.js поддерживаются все следующие варианты:

javascript
m('input', { readonly: true }); // нижний регистр
m('input', { readOnly: true }); // верхний регистр
m('input[readonly]');
m('input[readOnly]');

Это также относится и к пользовательским элементам. Например, вы можете использовать A-Frame в Mithril.js без каких-либо проблем!

javascript
m('a-scene', [
  m('a-box', {
    position: '-1 0.5 -3',
    rotation: '0 45 0',
    color: '#4CC3D9',
  }),

  m('a-sphere', {
    position: '0 1.25 -5',
    radius: '1.25',
    color: '#EF2D5E',
  }),

  m('a-cylinder', {
    position: '1 0.75 -3',
    radius: '0.5',
    height: '1.5',
    color: '#FFC65D',
  }),

  m('a-plane', {
    position: '0 0 -4',
    rotation: '-90 0 0',
    width: '4',
    height: '4',
    color: '#7BC8A4',
  }),

  m('a-sky', {
    color: '#ECECEC',
  }),
]);

Для пользовательских элементов автоматическое преобразование свойств в строку не выполняется, если они являются объектами, числами или другими нестроковыми значениями. Поэтому, если у вас есть какой-то пользовательский элемент my-special-element, у которого есть свойство getter/setter массива elem.whitelist, вы можете сделать это, и это будет работать так, как вы ожидаете:

javascript
m('my-special-element', {
  whitelist: [
    'https://example.com',
    'https://neverssl.com',
    'https://google.com',
  ],
});

Если у вас есть классы или идентификаторы для этих элементов, сокращения по-прежнему работают так, как вы ожидаете. Чтобы привести еще один пример A-Frame:

javascript
// Эти два эквивалентны
m('a-entity#player');
m('a-entity', { id: 'player' });

Обратите внимание, что все свойства с магической семантикой, такие как атрибуты жизненного цикла, обработчики onevent, key, class и style, по-прежнему обрабатываются так же, как и для обычных HTML-элементов.

Атрибут style ​

Mithril.js поддерживает как строки, так и объекты в качестве допустимых значений для style. Другими словами, поддерживаются все следующие варианты:

javascript
m('div', { style: 'background:red;' });
m('div', { style: { background: 'red' } });
m('div[style=background:red]');

Использование строки в качестве style перезапишет все встроенные стили элемента при его перерисовке, а не только те правила CSS, значения которых изменились.

Вы можете использовать как имена свойств CSS с дефисами (например, background-color), так и имена свойств style DOM в стиле camel case (например, backgroundColor). Вы также можете определить пользовательские свойства CSS, если ваш браузер их поддерживает.

Mithril.js не пытается добавлять единицы измерения к числовым значениям. Он просто преобразует их в строку.

События ​

Mithril.js поддерживает регистрацию обработчиков событий для всех DOM-событий, включая события, спецификации которых не определяют свойство on${event}, такие как touchstart.

javascript
function doSomething(e) {
  console.log(e);
}

m('div', { onclick: doSomething });

Mithril.js принимает функции и объекты EventListener. Так что это тоже будет работать:

javascript
var clickListener = {
  handleEvent: function (e) {
    console.log(e);
  },
};

m('div', { onclick: clickListener });

По умолчанию, при срабатывании события, привязанного через hyperscript, Mithril.js автоматически выполнит перерисовку после завершения callback-функции (если используется m.mount или m.route вместо m.render). Вы можете отключить автоматическую перерисовку для конкретного события, установив для него e.redraw = false:

javascript
m('div', {
  onclick: function (e) {
    // Предотвратить автоматическую перерисовку
    e.redraw = false;
  },
});

Свойства ​

Mithril.js поддерживает функциональность DOM, доступную через свойства, такие как свойства selectedIndex и value элемента <select>.

javascript
m('select', { selectedIndex: 0 }, [
  m('option', 'Option A'),
  m('option', 'Option B'),
]);

Компоненты ​

Компоненты позволяют инкапсулировать логику в отдельный модуль и использовать его, как если бы это был элемент. Они являются основой для создания больших, масштабируемых приложений.

Компонент - это JavaScript-объект, содержащий метод view. Чтобы использовать компонент, передайте его в качестве первого аргумента в m() вместо строки CSS-селектора. Вы можете передавать аргументы компоненту, определяя атрибуты и дочерние элементы, как показано в примере ниже.

javascript
// определить компонент
var Greeter = {
  view: function (vnode) {
    return m('div', vnode.attrs, ['Hello ', vnode.children]);
  },
};

// использовать его
m(Greeter, { style: 'color:red;' }, 'world');

// отображает этот HTML:
// <div style="color:red;">Hello world</div>

Чтобы узнать больше о компонентах, см. страницу компонентов.

Методы жизненного цикла ​

Vnode и компоненты могут иметь методы жизненного цикла (также называемые hooks), вызываемые на разных этапах жизненного цикла DOM-элемента. Методы жизненного цикла, поддерживаемые Mithril.js: oninit, oncreate, onupdate, onbeforeremove, onremove и onbeforeupdate.

Методы жизненного цикла определяются так же, как и обработчики DOM-событий, но получают vnode в качестве аргумента, вместо объекта Event:

javascript
function initialize(vnode) {
  console.log(vnode);
}

m('div', { oninit: initialize });
HookОписание
oninit(vnode)Выполняется до того, как vnode будет отображён в реальный DOM-элемент.
oncreate(vnode)Выполняется после добавления vnode в DOM.
onupdate(vnode)Выполняется каждый раз, когда происходит перерисовка, пока DOM-элемент прикреплен к документу.
onbeforeremove(vnode)Выполняется до удаления DOM-элемента из документа. Если возвращается Promise, Mithril.js отсоединяет DOM-элемент только после завершения promise. Этот метод вызывается только для элемента, отсоединенного от родительского DOM-элемента, но не для его дочерних элементов.
onremove(vnode)Выполняется до удаления DOM-элемента из документа. Если определен хук onbeforeremove, onremove вызывается после вызова done. Этот метод вызывается для элемента, отсоединенного от родительского элемента, и для всех его дочерних элементов.
onbeforeupdate(vnode, old)Выполняется перед onupdate, и если он возвращает false, он предотвращает diff для элемента и всех его дочерних элементов.

Чтобы узнать больше о методах жизненного цикла, см. страницу методов жизненного цикла.

Ключи ​

Vnode в списке могут иметь специальный атрибут, называемый key, который можно использовать для управления идентификацией DOM-элемента при изменении данных модели, генерирующих список vnode.

Как правило, key должен быть уникальным идентификатором объектов в массиве данных.

javascript
var users = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Mary' },
];

function userInputs(users) {
  return users.map(function (u) {
    return m('input', { key: u.id }, u.name);
  });
}

m.render(document.body, userInputs(users));

Наличие ключа гарантирует, что при перемешивании массива users и перерисовке представления порядок элементов ввода сохранится, что позволит сохранить фокус и состояние DOM.

Чтобы узнать больше о ключах, см. страницу ключей.

SVG и MathML ​

Mithril.js полностью поддерживает SVG. Xlink также поддерживается, но, в отличие от версий Mithril.js до v1.0, должно быть явно определено пространство имен:

javascript
m('svg', [m("image[xlink:href='image.gif']")]);

MathML также полностью поддерживается.

Создание динамических шаблонов ​

Поскольку вложенные vnode являются обычными JavaScript-выражениями, для управления ими можно использовать стандартные средства JavaScript.

Динамический текст ​

javascript
var user = { name: 'John' };

m('.name', user.name); // <div class="name">John</div>

Циклы ​

Используйте методы Array, такие как map, для итерации по спискам данных.

javascript
var users = [{ name: 'John' }, { name: 'Mary' }];

m(
  'ul',
  users.map(function (u) {
    // <ul>
    return m('li', u.name); //   <li>John</li>
    //   <li>Mary</li>
  })
); // </ul>

// ES6+:
// m("ul", users.map(u =>
//   m("li", u.name)
// ))

Условные выражения ​

Используйте тернарный оператор для условной установки содержимого в представлении.

javascript
var isError = false;

m('div', isError ? 'An error occurred' : 'Saved'); // <div>Saved</div>

Вы не можете использовать операторы JavaScript, такие как if или for, внутри JavaScript-выражений. Предпочтительно вообще избегать использования этих операторов и вместо этого использовать только вышеуказанные конструкции, чтобы сохранить структуру шаблонов линейной и декларативной.

Преобразование HTML ​

В Mithril.js правильно сформированный HTML является допустимым JSX. Для интеграции независимо созданного HTML-файла в проект с использованием JSX требуется немного усилий, кроме копирования и вставки.

При использовании hyperscript необходимо преобразовать HTML в синтаксис hyperscript, прежде чем код будет запущен. Чтобы облегчить это, вы можете использовать конвертер HTML-в-Mithril-шаблон.

Избегайте анти-паттернов ​

Хотя Mithril.js является гибким, некоторые шаблоны кода не рекомендуются:

Избегайте динамических селекторов ​

Разные DOM-элементы имеют разные атрибуты и часто разное поведение. Использование настраиваемого селектора может раскрыть детали реализации компонента.

javascript
// ИЗБЕГАЙТЕ
var BadInput = {
  view: function (vnode) {
    return m('div', [m('label'), m(vnode.attrs.type||'input')]);
  },
};

Вместо того, чтобы делать селекторы динамическими, рекомендуется явно кодировать каждую допустимую возможность или рефакторить переменную часть кода.

javascript
// ПРЕДПОЧТИТЕЛЬНЕЕ явный код
var BetterInput = {
  view: function (vnode) {
    return m('div', [m('label', vnode.attrs.title), m('input')]);
  },
};
var BetterSelect = {
  view: function (vnode) {
    return m('div', [m('label', vnode.attrs.title), m('select')]);
  },
};

// ПРЕДПОЧТИТЕЛЬНЕЕ рефакторинг изменчивости
var BetterLabeledComponent = {
  view: function (vnode) {
    return m('div', [m('label', vnode.attrs.title), vnode.children]);
  },
};

Избегайте создания vnode вне представлений ​

Если при перерисовке встречается vnode, строго равный vnode в предыдущем рендере, он пропускается, и его содержимое не обновляется. Хотя это может показаться возможностью для оптимизации производительности, этого следует избегать, поскольку это предотвращает динамические изменения в дереве этого узла - это приводит к побочным эффектам, таким как сбой при запуске методов жизненного цикла ниже по потоку при перерисовке. В этом смысле Mithril.js vnode являются неизменяемыми: новые vnode сравниваются со старыми; изменения в vnode не сохраняются.

Документация по компонентам содержит более подробную информацию и пример этого анти-паттерна.

Pager
Предыдущая страницаAPI
Следующая страницаrender(element, vnodes)

Выпущено на условиях лицензии MIT.

Авторские права (c) 2024 Mithril Contributors

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

Выпущено на условиях лицензии MIT.

Авторские права (c) 2024 Mithril Contributors