Pull to refresh

Comments 56

jsx конечно удобен, но он всё таки не панацея

mol слишком революционен для масс. Я, например, так и не понял, как мне с помощью mol подключить реактивность на HTML-страницу. Вот пример, как подключается vue-реактивность:

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<div id="app">{{ message }}</div>

<script>
  const { createApp, ref } = Vue

  createApp({
    setup() {
      const message = ref('Hello vue!')
      return {
        message
      }
    }
  }).mount('#app')
</script>

У Cample.js та же самая проблема - я не вижу, как его подключить к существующей HTML-странице и использовать в качестве внешней библиотеки (как тот же jQuery).

Это одна из причин, почему я у себя использую vue. Web-приложение - это прежде всего HTML/CSS/JS (WebAssembly пока и близко не стоит к). Всё остальное в веб-разработке лишь инструментарий для сведения к этой триаде чего угодно (включая TypeScript, и включая Tree).

Притягивая за уши аналогии с церковью: зачем мне говорить со священником, если я могу говорить напрямую с Богом?

В нем нет объяснения, где я возьму исходник для этого импорта:

import { $mol_wire_dom, $mol_wire_patch } from "mol_wire_dom";

Это не работающий пример. Рабтающий пример вот: https://jsfiddle.net/05hm6Lkt/

<div id="root">

  <div id="form">
  
    <input id="nickname" value="Jin" />
    <button id="clear">Clear</button>
    
    <label>
      <input id="greet" type="checkbox" /> Greet
    </label>
    
  </div>

  <p id="greeting">...</p>

</div>

<script src="https://unpkg.com/mol_wire_dom/web.js"></script>

<script>
// Make DOM reactive
$mol_wire_dom( document.body )

// Take references to elements
const root = document.getElementById( 'root' )
const form = document.getElementById( 'form' )
const nickname = document.getElementById( 'nickname' )
const greet = document.getElementById( 'greet' )
const greeting = document.getElementById( 'greeting' )
const clear = document.getElementById( 'clear' )

// Set up reactive formulas
greeting.__defineGetter__( 'textContent', ()=> 'Hello ' + nickname.value + '!' )
root.__defineGetter__( 'childNodes', ()=> greet.checked ? [ form, greeting ] : [ form ] )

// Set up handlers
clear.onclick = ()=> nickname.value = ''
</script>

Вот этот код мне удалось запустить на простой HTML-странице. И он даже работает!

Теперь такой вопрос - что такое textContent и что такое childNodes ? На сайте https://mol.hyoo.ru/ мне не удалось ничего найти про первое даже с использованием полей поиска. Поиск на гугле по ключу "textContent site:mol.hyoo.ru" также дал ничего.

Допустим, я хочу подключить вашу реактивность взамен vue-реактивности в своём новом проекте (HTML/CSS/JS) - где мне искать информацию по доступному функционалу?

Вот честно, я туповат для того, чтобы разобраться с вашим фреймворком самостоятельно. В этот раз я дошёл до работающего кода на HTML-странице, но вау-эффекта не получилось :( Я вижу, что вы вешаете какой-то дополнительный функционал на элементы DOM'а и что есть какой-то magic в $mol_wire_dom, который этот функционал использует (и ещё свой добавляет, скорее всего). При этом вы не трогаете исходный DOM. И у меня возникает вопрос за таблицы/гриды - а как вы не трогая исходный DOM, выводите списки - функциональю? Как бы HTML декларативный язык. Я именно поэтому и использую vue, что он, по сути, просто добавляет свои компоненты, как новые тэги в HTML, а свой функционал - как новые атрибуты:

<li v-for="item in items">
  {{ item.message }}
</li>

Для меня, как для разработчика, это офигенно удобно. Я с радостью плачу за это скоростью рендеринга - современные мощности это позволяют. А как сделать аналогичный список на mol?

Теперь такой вопрос - что такое textContent и что такое childNodes

Это DOM API.

как вы не трогая исходный DOM, выводите списки - функциональю?

В chidNodes возвращаете список дом элементов.

А как сделать аналогичный список на mol?

Кажется эта шутка зашла слишком далеко. Не надо так делать, на $mol так не пишут. На $mol интерфейс собирают из компонент, а не верстают html. Тут есть краткое введение.

Я хотел примерно посчитать кол-во символов в вашем "кратком введении", но... у меня не получилось. Казалось бы, чего проще - выделить текст (мышкой или с клавиатуры), скопировать его в текстовый файл и посмотреть размер в байтах (поделив на два для юникода). Даже Ctrl + A не сработало. Даже Save as...

Получилось только распечатать страницу в PDF-файл по Ctrl + P и уже после этого смог перенести содержимое из pdf в текстовый файл. 32715 байтов, т.е. порядка 16К символов. Ну, такое себе краткое объяснение построения списков через mol.

По итогу я так и не могу использовать mol в качестве библиотеки реактивности, а строить своё приложение полностью на mol... Может быть после того, как команда Тинькофф банка освоит вашу платформу. Слишком уж эта платформа революционна, не мой уровень.

А по поводу, что в mol интерфейс собирают из компонент, а не верстают HTML. Смотрите, внутри всё та же триада - HTML/CSS/JS:

Только теперь к ней нужно продираться не только через TS, но ещё и через Tree.

Это у нас защита от копирования такая. Надо бы запретить печать, чтобы вы перестали воровать мои статьи.

Документация с защитой от копирования? Это ж насколько вам не хочется популярности своего фреймворка...

Так это BDSM фреймворк, сначала больно, неприятно, а потом за уши не оттащишь.

Прочитал первый абзац. Не вижу смысла продолжать. Уровень йумора заставляет предположить, что аффтары не умеют в документацию и не видят этого

Я не из секты @nin-jin но мне в принципе понятно, как работает этот код. С root по clear - Это ссылки на DOM-элементы, а textContent и childNodes это нативные свойства элементов. И геттеры также работали бы, даже если бы не было вызова $mol_wire_dom. Очевидно, что реактивность над DOM можно получить за счет на подписок события модификации элементов.

Заглянул в $mol_wire_dom, так оно и оказалось.

А так, согласен с Вами, что нет легкого старта. Собственно, если высокий порог вхождения и нет явного коммерческого интереса, то туда никто и не войдет.

Для подключения реактивности к готовому HTML я использую микрофреймворк Sinous (2.2Kb Gzip)

https://sinuous.netlify.app/docs/hydrate/ – документация, где описывается, как это сделать.

Из всех подходов, которые я видел, этот, на мой взгляд, самый удобный. Что касается версии 0.3.2 – меня это не беспокоит, фреймворк уже более года трудится на проде, ошибок и замечаний нет.

Каким образом mol обгоняет vanillajs в три раза?

За счёт включенной по умолчанию виртуальной прокрутки с ленивым рендером. Той самой, которая мешает работать поиску по странице средствами браузера, работает в качестве защиты от копирования, и ломает поведение кнопки "назад" в браузере. А, ещё оно заставляет полосу прокрутки лагать.

Так это тогда ерунда какая-то. Суть бенчмарка состоит в сравнении накладных расходов фреймворков при выполнении одинаковых операций, а не в сравнении, у кого список хитрее написан.

А есть результат с выключенным ленивым рендером? В оригинальном репозитории я ничего с названием mol не нашел.

Список везде тривиально написан. Разница только в библиотеках рендера. И сравнение идёт именно отзывчивости для пользователя, а не скорости выполнения одних и тех же инструкций, иначе разницы в показаниях вообще бы не было.

В конкретном бенчмарке сравниваются накладные расходы на выполнение одинаковых операций, а не отзывчивость. Условно, кнопка "Create 1,000 rows" должна создавать 1000 элементов в dom, даже если фреймворк умеет в ленивый рендеринг. Поэтому я и спрашивал, есть ли результат mol с отключенным ленивым рендерингом?

А вам бенчмарки, простите, для чего? Письками меряться или делать приложения, которые не тормозят? Пользователю эти ваши 1000 строк зачем, если он видит лишь 20 из них?

Бенчмарк выше мне нужен для сравнения накладных расходов фреймворков при условии выполнения ими одинаковой работы.

Я мог бы добавить виртуальный скролл в Angular или React и сравнить, но тогда бы к накладным расходам на хранение компонентов, биндинги и всего такого еще бы добавилась разница в реализации виртуального скролла, что нежелательно.

Поэтому я интересуюсь, можно ли получить результат mol без виртуального скролла?

VDOM, IDOM и RDOM, очевидно, выполняют разную работу. Вас это не смущает? Или возмущает только использование техник минимизации работы, которые не поддерживаются вашей любимой технологией?
Ладно, не буду повторяться, вам сюда: https://page.hyoo.ru/#!=rmdua_5l8qt5

Меня вообще ничего не смущает. Да, в Angular нет виртуального скролла из коробки, но я могу подключить стороннее решение парой строчек и использовать его. Думаю в других фреймворках все так же.

По вашей ссылке сходил, отжал всю воду, вот суть: "в mol работает virtual-scroll по умолчанию. Во Vue тоже что-то есть, но глючное и не по умолчанию". Что там было во Vue неясно, потому что одна ссылка ведет на реализацию на mol, другая ведет на 404.

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

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

Видимо автору реализации на Vue стало стыдно, и он скрыл репозиторий. Бывает.

Если бы вы внимательно прочитали свою же статью, то вы бы заметили, что там не объясняется, почему "прикручивание "виртуального скролла" ко фреймворку, который в него не умеет, в общем случае весьма нетривиальная задача", там это просто утверждается. Я понимаю, что написание вирт. скролла является нетривиальной задачей, но у меня с ее решением нет проблем.

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

Успехов вам в прикручивании вирт скролла к дереву комментариев на Хабре.

Никак, в $mol нельзя говнокодить by design.

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

При прокрутке уже отрисовывать нужную часть страницы так, как она должна выглядеть.

"Текстовые" блоки можно лениво рендерить, чтобы браузер не тормозил.

Если не уничтожать, то скорость будет деградировать при прокрутке.
А если рендерить текст без вёрстки, то браузерному поиску это не поможет, ибо он будет не туда, куда надо.

браузерному поиску это не поможет, ибо он будет не туда, куда надо.

<div style="height: 90px">long text </div>
<div style="height: 120px">long text 2 </div>
...
<div style="height: 20px">needle in a haystack </div>
...
<div style="height: 200px">text </div>

Div мог бы быть в исходном контенте параграфом или таблицей. Это неважно потому что тут главное позиционирование текстовых блоков (следование друг за другом с учетом их размеров).

Поэтому, как мне кажется, если искать needle, то браузер покажет его в нужном и правильном месте только в случае проведенных предварительных расчетов высот таких элементов. Или я что-то упускаю?

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

Чтобы продемонстрировать что я имею в виду, накидал небольшой сниппет для замены комментариев Хабра теми самыми текстовыми блоками.

let nodes = Array.from(document.querySelectorAll(".tm-comment-thread__comment"));

for (let i=0; i<nodes.length; i++) {
    let node = nodes[i];
    let rect = node.getClientRects()[0];
    let text = node.innerText;
    let div = document.createElement("div");
    div.style.height = `${rect.height}px`;
    div.innerText = text;

    node.replaceWith(div);
}

Помимо необходимости знать точные размеры (что равносильно полному рендеру) будет ещё и проблема со скачками в никуда из-за замены одного блока на другой.

Чтобы скачков не было в бесконечных списках обычно используют position: absolute.

Полностью согласен, что упираемся в расчеты, которые не хочется проводить на клиенте. Но и это решаемо, потому что именно разработчик компонента (возможно с поддержкой дизайнера) решает как он должен отображаться. Я к тому что чем больше строгости, тем проще расчеты.

В том числе расчеты могут быть отложенными и незаметными для пользователя. И могут даже корректироваться, переходя от приближенных расчетов высот к более точным ) Потому что нам будет все равно, что условный компонент, который ниже вьюпорта на 5000px на самом деле должен быть 4950px. При скроллинге это незаметно.

Вы всё же почитайте статью по заминусованной ссылке выше. Там всё это разбирается. Ну или сами попробуйте всё это реализовать.

А можно с AlpineJS сравнить? Или я настолько старый, что это уже не используется?

Ещё не понедельник, а уже новый js-фреймворк)))

И вновь реактивный)

отлично, теперь у нас будет плодиться параллельно ветка "безVDOMовых" фреймворков

Буду очень рад, ведь это явный вклад в развитие технологии!

Кто разбирается в версионировании, объясните мне, пожалуйста:

Это не самый быстрый результат из всех, которые существуют на данный момент среди фреймворков

основан на реактивности без виртуального DOM, которая в теории может быть гораздо быстрее

большинство функций, которые необходимы сегодня для создания prod сайта пока не поддерживаются

А версия уже 3.0.1

Сейчас стало модно ставить большие версии. Ну типа смотри он уже 3й версии!!!
Значит это не какая-то альфа шляпа, а над ним работали огого сколько, реди ту прод!
Кароче чисто маркетинг.

Версии к 50й будет юзабельным.

Возможно это особенность semver-схемы версионирования. Тот же Laravel как на неё перешёл, как начал версии на гора выдавать с огромной скоростью.

Сейчас? DBase III не имела второй и первой версии. Можно сказать, что "ставить большие версии не вышло из моды".

Дело не в маркетинге. Но, насчёт 50 версии - вы полностью правы

Просто честный SemVer. Как только потеряли обратную совместимость - повышаем старшую версию. Если добавили функциональность - повышаем младшую версию. Если изменили код, но это ни как не отразилось вводе и ввыводе наших методы, то меняем версию патч а.

Я рефакторил свою библиотеку для XML, каждый этап рефакторинга делал релиз, я начал с версии 2 и закончил версией 7. По функционалу изменилось не многое, но обратная совместимость была жертвой этого рефакторинга, поэтому приходилось повышать старшую версию. При этом младшие версии повышались когда раз когда два.

Быстрый рост версий - это следствие частых иелизов и честного следования семантике версий.

Так, пока фреймворк делался, надо было версии делать. Я ставил версию 1, 2 и 3 только тогда, когда понимал, что там действительно много всего нового и что фреймворк отличается конкретно от прошлой. Там можно посмотреть по коду это

Версии до первого релиза обычно нумеруют как 0.1, 0.2, 0.3...

Да, обычно так и нумеруется. Я. наверное, больше на node.js ориентировался, как там 18 версия и т.д

Хорошо, что на виндоус не ориентировались, а ты следующую версию уже 95 надо было бы выпускать :)

Там у них свои версии. Там то windows 95, то windows 2000, то после 8 версии 10 сразу

Где-то там нужно было бы воткнуть NT 4.0 и Millenium

Игра на выпивание.
Каждый по очереди берет английский словарь и выбирает случайное слово. После чего он гуглит <слово>.js, и пьет, если есть такая библиотека или фреймворк для javascript. Выигрывает тот, кого последнего госпитализируют с алкогольным отравлением.
(с) интернет.

Sign up to leave a comment.

Articles