Комментарии 61
Мм ручное управление реактивностью
Но фреймворк сам проставляет реактивные зависимости вручную в момент компиляции компонента.
UPD: Прям с ходу:http://sexy-js.ninja/docs/single-file-components/reactivity
> Так делать не стоит, значение изменится, но обновления DOM не запустятся
Так разработчик явно помечает реактивные данные, точно также, как вы это делаете в других фреймворках.
Насчёт того, как делать не стоит, можете уточнить, что имеете в виду?
Пока единственная проблема (но она решаема) это полная реактивность объектов
Что конкретно вы имеете в виду?
class State {
@observable counter = 1;
increment = () => {
this.counter++;
};
}
const state = new State();
export const App = observer(() => {
return (
<div>
<h1>Counter: {state.counter}</h1>
<button onClick={state.increment}>incr</button>
</div>
);
});
Вот это настоящая реактивность. Уже дофига лет в JS существуют getters/setters, а с появлением ES6 появилась Proxy, что делает реактивность ещё круче.
codesandbox.io/s/frosty-hawking-jz7gg?file=/src/App.tsx
Во первых, на прямую во фреймворках вы со всем этим все равно не работаете.
Во вторых, вы говорите про то, как реактивность работает под капотом.
Не понимаю вашего «лол» и что я должен понять из приведённого участка кода. А самое главное, что в проекте на текущий момент сделано не так как надо.
То есть this.counter++ работает как ожидается, а у вас надо counter(counter() + 1);
Или же this.item.name = 'asd' в MobX работает как ожидается, а у вас надо дополнительно вызывать руками функцию для вызова реакций
Верно. Как указали ниже, обёртку можно и другую использовать, это не проблема.
Проблемы появляются когда используются вычисляемые свойства. Любая реактивная библиотека запускает subscriber, чтобы проставить зависимости. Это добавляет лишнее время на запуск js кода. Когда у вас 10 компонентов — это не критично, но когда у вас много статики, тогда время до интерактивности улетает в небеса.
Computed есть, транзакций пока нет, но тоже добавить реально.
Единственное, что делает Фреймворк, он проставляет зависимости для computed и subscriber без вызова функции на этапе компиляции. Чтобы не вызывать эту функцию в рантайме
транзакций пока нет, но тоже добавить реально
вот с этим как раз больше всего проблем возникнет. Наиболее интересная на эту тему статья на на хабре: Изучаем и реализуем алгоритм работы правильного observer паттерна для react компонентов. Она, конечно, сильно облегчит вам работу, но может не стоит изобретать колесо? Посмотрите на cellx и на mobx. Оба решения отлично подходят для встраивания в фреймворки.
Так Я за, но они все вызывают функции для поиска зависимостей и от этого никуда не деться. Соотвественно просядет производительность, если есть какой то способ, как избежать этого, и вы его вдруг знаете, будет супер.
Зависимости вычисляются при каждом вызове вычисляемой ячейки. А как вам нужно?
Вычислять зависимости на этапе компиляции, чтобы при запуске на клиенте не выполнилась лишняя работа
Плохая это идея, посмотрите на следующий код:
let a = cellx(true);
let b = cellx(1);
let c = cellx(() => {
console.log('Compute "c"');
return a() || b();
});
c.subscribe(() => {});
b(2);
// => Compute "c"
a(false);
// => Compute "c"
b(3);
// нет вычисления "c"
При вычислении зависимостей на этапе компиляции они будут прибиты к вычисляемым ячейкам и в последней строке примера вместо 'нет вычисления "c"' будет 'Compute "c"', то есть лишнее вычисление. В конечном счёте на таких лишних вычислениях вы будете терять куда больше производительности. Плюс головная боль при отладке.
В вашем случае лишняя работа будет на рередер при изменении любой реактивной переменной от которой результат может зависеть в принципе, но не зависит в данный конкретный момент времени.
Да дело же не в DOM или биндингах, а в том, что есть статические зависимости, а есть динамические, которые могут быть определены лишь в рантайме. Например, зависимость может быть продиктована вводом пользователя. Я бы предложил реализовать динамический трекинг зависимостей и к нему в дополнение статический анализатор, который выявлял бы статические зависимости и прописывал их явно, исключая из трекинга. Не факт, что это сильно ускорит, конечно, но это будет хотя бы отличительной чертой.
Реактивные либы, если биндить зависимости, но пропускать работу рендера, работают отлично и никакого overhead не добавляют. Походу где-то я накосячил с предыдущим бенчем.
Попробую узнать, как можно внедрить в svelte. Будет круто, если не нужно будет дальше изобретать велик.
Не факт, что это сильно ускорит
почти совсем не ускорит, в cellx раньше была возможность помечать вычисляемые ячейки как ячейки со статичными зависимостями. То есть зависимости определялись только при первом вычислении и дальше этот механизм полностью отключался. На бенчмарках это вроде и давало какое-то очень скромное ускорение при повторных вычислениях, но там в пределах погрешности было, я пришёл к выводу, что оно просто не стоит каких-то усложнений в коде и плюс нужно такие ячейки ещё самому высматривать. В общем убрал.
Вот это настоящая реактивность.
в mobx просто другие обёртки над алгоритмом реактивности. Если сам алгоритм у kirBurkhanov написан хорошо, то не понимаю, что мешает считать такую реактивность настоящей. Дописать удобные обёртки (в тч. Proxy) делов на пару выходных.
Звучит очень сексуально. Но контрибьютить без документации, в особенности без знания дизайна и "философии" фрейма достаточно сложно. Пример аля hello world ничего толком не показывает.
Синтаксис добавить не проблема. Главное Это понять нужно ли новое решение, утвердить весь синтаксис и довести Фреймворк до production
«Потом» поддерживать @types — так себе занятие будет.
Я имел ввиду, что в шаблонах нет поддержки синтаксиса TS, есть элвис-оператор и все, нельзя использовать привидение типов и т.п.:
(item as SomeClass).prop1
И в input-binding можно подсунуть совсем не тот тип, что описан в компоненте
Почти так оно и есть, только Гидратация работает быстрее раз в 10.
В том то и дело, что весь базовый функционал реализован. А скорость при этом быстрая.
А можете показать пример проекта, где производительность реакта Вас устраивает?
Подскажите, есть ли роутинг? Я не фронтендер, но вроде для svelte он делается на стороне сервера (sapper), а в модных фремворках-клиента.
В принципе, есть всё необходимое для типичного низкоуровневого фронтенд фреймворка. Хорошая работа. Придраться можно разве что к:
- разный синтаксис обращения к переменным в яваскрипте и шаблонах, даже в разных местах шаблона он разный.
- двусторонний биндинг только для свойства
value
. Для html это может и сойдёт, но не для пользовательских компонент. - перенос компонента между родителями приводит к его полному ререндеру.
- судя по всему любое состояние, что находится вне скоупа компонента, не отслеживается — это источник множества багов.
2. Двусторонний биндинг можно кастомизировать с помощью своей директивы
3. Так и есть, как часто вообще используется «ручной» перенос?
4. На данный момент так и есть, нужен свой MobX, Vuex и т.д.
Проблем много, но они решаемы. Вопрос только нужно ли новое решение… И насколько остро стоит вопрос производительности при запуске фреймворка. А-ля замена «jQuery» для сайтов с изолированными компонентами и нормальным тестированием.
2) Писать по директиве для каждого параметра каждого компонента, где нужна двусторонняя связь — довольно утомительно.
3) В рамках списка переносы тоже ведь не в ручную делаются. Достаточно уметь идентифицировать компонент не в рамках одного списка, а глобально.
Вообще, если вы вообще задаётесь вопросом "а нужно ли?", то не нужно. Так вы слона не продадите. Сообщество не поддержит ещё один велосипед, даже если он будет лучше по всем показателям. Конкретно по производительности, пользователи уже привыкли, что сайты у них открываются по 10 секунд. Поэтому и разработчики не особо парятся на эту тему.
3. У меня в списке элементы заново не рендерятся. Так-то можно через привязку к ключу реализовать.
Конкретно по производительности, пользователи уже привыкли, что сайты у них открываются по 10 секунд.
Аналитика пользовательского поведения говорит немножко о другом: отказы прямо зависят от того, как медленно работает веб-сайт/приложение. Почему вы считаете, что пользователи привыкли и это не особо важно?
Потому что какой сайт ни откроешь — ждёшь по 10 секунд. Типичная картина выглядит как-то так:
И это приложение с не слишком сложной функциональностью от технологического лидера, где есть специалисты умеющие в оптимизацию, и делающие её постоянно. Про сайты для домохозяек, которые лепят студенты за гроши, и заикаться не стоит.
Сделал аналогичную кнопку с главной страницы, получилось 1кб виджет против 5кб на sexy-js
У вас есть пример TodoMVC для сравнения?, у меня оно весит всего 2.7kb
Сделаю, но скорее всего больше, цель была не размер сократить, а скорость сделать быструю.
Подход с innerHTML и template тоже использую.
Название фреймворк затруднит, по-моему, внедрение в серьёзных компаниях.
Самый sexy framework для веб-приложений