Реактивные обновления DOM с помощью Ruby.
живая демонстрация на rdom .fly.dev
встраивание демо в rdom .netlify.app
Это базовый эксперимент с VDOM на стороне сервера в Ruby. Для более полной реализации см. Mayu Live. У меня были некоторые идеи, которые, как мне казалось, мне нужно было изучить, и вот результат.
Убедитесь, что у вас есть Ruby 3.2 и Bundler, затем запустите:
bundle install
Чтобы запустить сервер:
ruby config.ru
Эта штука поставляется с сервером HTTP/2. Запустите его с помощью ruby config.ru
.
По умолчанию он привязывается к https://localhost:8080
, но его можно изменить, установив переменную окружения rdom _BIND
следующим образом: rdom _BIND="https://[::]" ruby config.ru
.
Это единственные строки HTML, необходимые для монтирования приложения.
< script type =" module " src =" https://rdom.fly.dev/ rdom .js " > </ script >
< rdom -embed src =" https://rdom.fly.dev/. rdom " > </ rdom -embed >
Вы можете использовать bin/transform
чтобы увидеть преобразованный вывод файла Haml.
Пример:
bin/transform app/List.haml
Этот репозиторий содержит библиотеку реактивных сигналов, созданную на основе SolidJS, Preact Signals и Reactively.
Приложения, созданные с помощью этого, могут передаваться только в потоковом режиме, сервер никогда не будет пытаться создать HTML для первоначального запроса. Если вам нужно использовать HTML в первоначальном запросе, обратите внимание на Mayu Live.
Если соединение разрывается, все состояние теряется. Если вы хотите попробовать что-то более надежное, посетите Mayu Live.
Все статические деревья DOM извлекаются в пользовательские элементы, поэтому, если вы напишете:
- items = %w[foo bar baz]
% ul
= items.map do |item |
% li = item
Затем будет сгенерирован этот код:
# frozen_string_literal: true
class self :: Component < VDOM :: Component :: Base
rdom _Partials = [
VDOM :: CustomElement [
:" rdom -elem-app꞉꞉my-component.haml-0" ,
'<ul><slot id="slot0"></slot></ul>'
] ,
VDOM :: CustomElement [
:" rdom -elem-app꞉꞉my-component.haml-1" ,
'<li><slot id="slot0"></slot></li>'
]
]
def render
items = %w[ foo bar baz ]
H [
rdom _Partials [ 0 ] ,
slots : {
slot0 : items . map { | item | H [ rdom _Partials [ 1 ] , slots : { slot0 : item } ] }
}
]
end
end
Браузер предоставит вам:
< rdom -elem-my-component .haml-0 >
#shadow-dom
< ul > < slot > </ slot > </ ul >
< li >
< slot id =" slot0 " >
< rdom -elem-my-component .haml-1 > ↴
< rdom -elem-my-component .haml-1 > ↴
< rdom -elem-my-component .haml-1 > ↴
</ slot >
</ li >
< rdom -elem-my-component .haml-1 >
#shadow-dom
< li >
< slot id =" slot0 " >
< #text > ↴
</ slot >
</ li >
foo
</ rdom -elem-my-component .haml-1 >
< rdom -elem-my-component .haml-1 >
#shadow-dom
< li >
< slot id =" slot0 " >
< #text > ↴
</ slot >
</ li >
bar
</ rdom -elem-my-component .haml-1 >
< rdom -elem-my-component .haml-1 >
#shadow-dom
< li >
< slot id =" slot0 " >
< #text > ↴
</ slot >
</ li >
baz
</ rdom -elem-my-component .haml-1 >
</ rdom -elem-my-component .haml-0 >
Каждому слоту внутри теневого DOM будут назначены узлы при каждом обновлении дочерних элементов.
Это хорошо по нескольким причинам:
Каждый пользовательский элемент имеет :host { display: contents; }
чтобы избежать взаимодействия с гибкостью и сеткой.