Крошечный (512 байт) шаблонный механизм виртуального DOM для встроенных проектов
| Т.е. / Edge | Firefox | Хром | Сафари | Опера | ios safari | Chrome для Android |
|---|---|---|---|---|---|---|
| Край 14+ | 45+ | 49+ | 10+ | 37+ | 10.2+ | 55+ |
.dom заимствует некоторые концепции из React.js (например, многоразовые компоненты и виртуальный DOM) и пытается воспроизвести их с наименьшим возможным следствием, используя функции JavaScript ES6.
Почему? Потому что с такой библиотекой вы можете создать мощные графические интерфейсы в жестких космических средах, таких как устройства IoT, где сохранение даже дополнительного байта на самом деле имеет значение!
Крошечный по дизайну : библиотека никогда не должна превышать размеры 512 байтов. Цель состоит не в том, чтобы иметь еще один шаблонный двигатель, а иметь как можно больше функций в 512 байтах. Если необходима новая функция, другая должна быть сабрафизирована или прицел должен быть уменьшен.
Построенный в будущем : библиотека сильно использует спецификации ES6, что означает, что она не поддерживается более старыми браузерами. В настоящее время его поддерживают 90% браузеров на рынке, но ожидают, что это будет почти 100% в течение следующего года.
Декларатив : Опишите свой HTML DOM структурированным, естественным образом, помогая вам создать мощные, но читаемые пользовательские интерфейсы.
Компонентный ориентирован : точно так же, как React.js, .dom способствует использованию функциональных компонентов.
«Пишите меньше» ускорителей : библиотечный API разработан специально для того, чтобы иметь короткие имена функций и ускорители, что позволяет вам описать ваши представления с меньшим кодом.
.dom Вы используете .dom в своем проекте? Вилка этого репозитория и добавьте свой в список!
Для минимальной площади, включите dotdom.min.js.gz (512b) в ваш проект.
< script src =" dotdom.min.js.gz " />В качестве альтернативы вы можете просто включить мини -версию библиотеки непосредственно перед вашим сценарием. Просто скопируйте вставку мини-код.
Если вы уже знаете React.js, следующие примеры могут помочь вам понять, как примитивы .dom связаны с реагированием.
Предоставление очень простой структуры DOM.
| Реагировать | .dom |
|---|---|
ReactDOM . render (
React . createElement ( 'div' , null , 'Hello world' ) ,
document . body
) ; | R (
H ( 'div' , 'Hello world' ) ,
document . body
) |
Создание компонента, на котором вы можете пройти свойства.
| Реагировать | .dom |
|---|---|
function Hello ( props ) {
return React . createElement (
'div' , null , `Hello ${ props . toWhat } `
) ;
}
ReactDOM . render (
React . createElement (
Hello , { toWhat : 'World' } , null
) ,
document . body
) ; | function Hello ( props ) {
return H ( 'div' , `Hello ${ props . toWhat } ` ) ;
}
R (
H ( Hello , { toWhat : 'World' } ) ,
document . body
) |
Создание компонентов, которые могут поддерживать свое собственное состояние.
| Реагировать | .dom |
|---|---|
class Clickable extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
clicks : 0
} ;
}
render ( ) {
const { clicks } = this . state ;
return React . createElement (
'button' , {
onClick ( ) {
this . setState ( { clicks : clicks + 1 } )
}
} , `Clicked ${ clicks } times`
) ;
}
}
ReactDOM . render (
React . createElement ( 'div' , null ,
React . createElement ( Clickable , null , null ) ,
React . createElement ( Clickable , null , null )
) ,
document . body
) ; | function Clickable ( props , state , setState ) {
const { clicks = 0 } = state ;
return H ( 'button' ,
{
onclick ( ) {
setState ( { clicks : clicks + 1 } )
}
} ,
`Clicked ${ clicks } times`
) ;
}
R (
H ( 'div' ,
H ( Clickable ) ,
H ( Clickable )
) ,
document . body
) |
Компонент также может подписаться на события жизненного цикла:
| Реагировать | .dom |
|---|---|
class WithLifeCycle extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
mounted : "no"
} ;
}
componentDidMount ( ) {
this . setState ( { mounted : "yes" } )
}
render ( ) {
const { mounted } = this . state ;
return React . createElement (
'div' , null , `mounted = ${ mounted } `
) ;
}
}
ReactDOM . render (
React . createElement ( 'div' , null ,
React . createElement ( WithLifeCycle , null , null ) ,
) ,
document . body
) ; | function WithLifeCycle ( props , state , setState , hooks ) {
const { mounted = "no" } = state ;
hooks . m . push ( ( ) => {
setState ( { mounted : "yes" } )
} ) ;
return H ( 'div' ,
`mounted = ${ mounted } `
) ;
}
R (
H ( 'div' , H ( WithLifeCycle ) ) ,
document . body
) |
Ключевые обновления - это полезная функция сверки от React, которая позволяет рендерингу принять умные решения, по которым элементы обновления.
Особенно полезный случай - это когда вы составляете динамический список элементов. Поскольку двигатель рендеринга не понимает, какой элемент изменился, он заканчивается неправильными обновлениями.
Чтобы решить эту проблему, двигатели VDOM используют свойство key , которое уникально идентифицирует элемент в дереве. Однако .dom решает, сохраняя копию состояния элемента в самом экземпляре элемента VDOM.
Это означает, что вам не нужна какая -либо свойство key , просто убедитесь, что вы возвращаете тот же экземпляр VDOM, что и раньше.
Если вы создаете динамические элементы (например, массив элементов VDOM ), может возникнуть проблемы с обнаружением правильного порядка обновления.
| Реагировать | .dom |
|---|---|
class Clickable extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
clicks : 0
} ;
}
render ( ) {
const { clicks } = this . state ;
const { ket } = this . props ;
return React . createElement (
'button' , {
onClick ( ) {
this . setState ( { clicks : clicks + 1 } )
}
} , `clicks= ${ clicks } , key= ${ key } `
) ;
}
}
const list = [ "first" , "second" , "third" ] ;
const components = list . map ( key =>
React . createElement ( Clickable , { key } , null ) ;
ReactDOM . render (
React . createElement ( 'div' , null ,
components
) ,
document . body
) ; | function Clickable ( props , state , setState ) {
const { clicks = 0 } = state ;
const { key } = props ;
return H ( 'button' ,
{
onclick ( ) {
setState ( { clicks : clicks + 1 } )
}
} ,
`clicks= ${ clicks } , key= ${ key } `
) ;
}
const list = [ "first" , "second" , "third" ] ;
const components = list . map ( key =>
H ( Clickable , { key } ) ;
R (
H ( 'div' , components ) ,
document . body
) |
Обратите внимание, что приведенное выше решение правильно обновляет компоненты Stateful, даже если их заказ изменился. Однако, если вам нужна полная функциональность, подобная реагированию, которая обновляет отдельные ключи, вы можете использовать плагин Keyed .
function Container ( props , state ) {
const { components } = props ;
// The function `K` accepts the component state and an array of components that
// contain the `key` property, and returns the same array of components, with their
// state correctly manipulated.
return H ( "div" , K ( state , components ) ) ;
} Вы можете создать необработанные (не сообразительные) VDOM -узлы (например, несут произвольный HTML -контент), установив свойство .r Klocks объекта к любому значению правды.
Это отключит дальнейшее примирение с детскими узлами и, следовательно, сохранит ваше содержимое нетронутым.
function Description ( props , state , setState , hooks ) {
const { html } = props ;
hooks . r = 1 ; // Enable raw mode
return H ( 'div' , {
innerHTML : html
} )
} R( VNode, DOMElement ) R ( H ( 'div' , 'Hello' ) , document . body )Отдает данное дерево vnode в заданный элемент DOM. Дальнейшие обновления от государственных компонентов будут происходить только на их ближайших детях.
H( tagName | function, [properties], [children ...]) H ( 'tag' )
H ( 'tag' , { prop : "value" } )
H ( 'tag' , H ( 'child' ) )
H ( 'tag' , { prop : "value" } , H ( 'child' ) )
H ( Component , { prop : "value" } )Создает элемент VNODE. Если строка передается как первый аргумент, она создаст элемент HTML. Если функция дана, она создаст состоятельную компонент.
Свойства и дети являются необязательными, и они могут быть опущены.
Вместо имени тега вы можете предоставить функцию, которая возвращает виртуальный DOM в соответствии с некоторой логикой более высокого уровня. Такая функция имеет следующую подпись:
const Component = ( props , state , setState , hooks ) {
// Return your Virtual DOM
return div ( ... )
} Свойство props содержит объект свойств, как указано при создании компонента.
state инициализируется к пустому объекту {} и обновляется, вызывая метод setState({ newState }) . Последнее также запустит обновление компонента и это дети.
Вы также можете назначить свойства напрямую объекту state если вы не хотите вызывать обновление.
Объект hooks может использоваться, когда вы хотите зарегистрировать обработчики для методов жизненного цикла компонентов.
Подобно реагированию, компоненты .dom имеют жизненный цикл:
Чтобы получить доступ к методам жизненного цикла, вам необходимо использовать четвертый аргумент для вашей компонентной функции. Более конкретно вам нужно подтолкнуть функцию обработки в любом из следующих полей:
const Component = ( props , state , setState , hooks ) {
hooks . m . push ( ( domElement ) => {
// '.m' is called when the component is mounted
} ) ;
hooks . u . push ( ( ) => {
// `.u` is called when the component is unmounted
} ) ;
hooks . d . push ( ( domElement , previousDomElement ) => {
// `.d` is called when the component is updated
} ) ;
...
}tag( [properties], [children ...] ) const { div , span , a } = H ;
div ( 'hello' , span ( 'world' ) )
div ( 'click' , a ( { href : '#' } , 'Here' ) , 'to continue' ) Функция сокращения может быть извлечена в качестве свойства из H -функции. Такие сокращения ведут себя точно так же, как H , но с уже заполненным именем тега.
Рекомендуется использовать назначение деконструкции в начале вашего сценария, чтобы помочь минивер GavaScript еще больше оптимизировать результат:
const {div, span, a, button} = H;
tag.class( [properties], [children ...] ) const { h1 , span , p } = H ;
h1 . short ( 'short header' , span . strong ( 'strong text' ) )
button . primary ( { onclick : handleClick } , 'Primary Action' )
p . bold . italic ( twitterPost ) Вместо того, чтобы предоставлять className в качестве свойства, вы можете использовать .className .
Это то же самое, что и вызов div({className: 'className'}) , а интерфейс функции точно такой же, как и выше.
Примечание. Вы можете добавить более одного класса, объединив более одного .class к тегу. Например: div.foo.bar такой же, как div({className: 'foo bar'}) .
Поскольку проект фокусируется на небольшом размере, в нем отсутствуют проверки здравомыслия. Это делает его восприимчивым к ошибкам. Будьте очень осторожны со следующими предостережениями:
Вы не можете запустить обновление с удалением свойства. Вместо этого вы должны установить новое свойство на пустое значение. Например:
// Wrong
R ( div ( { className : 'foo' } ) , document . body ) ;
R ( div ( { } ) , document . body ) ;
// Correct
R ( div ( { className : 'foo' } ) , document . body ) ;
R ( div ( { className : '' } ) , document . body ) ; Вы никогда не должны использовать недвижимость с именем $ в своих компонентах. Это сделает объект свойства, чтобы рассматриваться как виртуальный узел DOM, и приведет к неожиданным результатам.
// *NEVER* do this!
R ( H ( MyComponent , { $ : 'Foo' } ) , document . body ) K(state, components)В
plugin-keyed.min.js
Согласно их key собственности, обеспечивает состояние компонентов в списке. Это позволяет вам делать обновления, похожие на реакцию, такие как SO:
function ValueRenderer ( ... ) {
...
}
function MyComponent ( props , state ) {
const { values } = props ;
const components = values . map ( value => {
H ( ValueRenderer , {
key : value ,
value : value
} ) ;
} )
// Synchronize state of components, based on their key
return H ( 'div' , K ( state , components ) )
} Вы заинтересованы в содействии .dom ? Добро пожаловать! Просто обязательно следуйте руководящим принципам:
npm install
npm test && npm run build && ls -l dotdom.min.js.gz
Если проходят тесты, и размер dotdom.min.js.gz меньше или равен 512 байт, создайте запрос на вытяжение. В противном случае уменьшите свой объем или подумайте о другой реализации, чтобы вернуть его до 512 байтов.
Убедитесь, что правильно комментируйте ваш код, так как вам, скорее всего, вам придется сделать какой -то экстремальный взлом JavaScript. Gudeliens следующие:
/**
* Functions are commented as JSDoc blocks
*
* @param {VNode|Array<VNode>} vnodes - The node on an array of nodes to render
* ...
*/
global . R = render = (
vnodes , // Flat-code comments start on column 70 and
dom , // wrap after column 120.
/* Logical separations can be commented like this */
...Лицензирована по лицензии Apache, версия 2.0