Чистый навык: битва кода React, Vue, Rxjs и нативного JS

внешний интерфейс

предисловие

Это чисто техническая статья, похожая на "Демистификация наиболее потенциального API Vue-3.0》То же, что и _[0]_, меньше фона, больше кода, больше демо, быстрее.

Давайте сразу перейдем к теме.

задний план

Некоторое время назад разработчик написал в Твиттере, что при использовании Svelte для достижения тех же функций, что и в React_[1]_, код становится намного проще.

Код React, который он дал, выглядит следующим образом:

И код Svelte выглядит следующим образом:

Использование сложной обработки реакций для доказательства превосходства svelte — не совсем корректное сравнение.

Затем к испытанию присоединился Vue [2], и Ю Сяою дал свой код:

Так же лаконично, как версия Svelte выше.

Позже Сяою предоставил более совершенную версию с реф-сахаром.

Предположительно, в Твиттере:

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

1. Удобная для рендеринга формула React-Hooks

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

Дело в том, что люди слишком легко используют useState.

В vue-composition-api есть обёртки для данных о реактивности, такие как reactive и ref.

Независимо от того, сколько объектов реактивности генерируется в custom-vca, таких как useHeight, повторный рендеринг не будет генерироваться напрямую.

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

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

В соответствии с этим механизмом реактивности для написания кода требуется особая ментальная модель — наложение состояний/эффектов.

useHeight, если:

let [ref, height] = useHeight()


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

В большинстве случаев вместо предоставления состояния может быть лучше предоставить эффекты. Как следующее:

let [height, setHeight] = useState(0)

let ref = useHeight((height) => {
  // do something with height
  setHeight(height)
})


Пользователь должен объявить состояние извне, а затем установитьHeight по мере необходимости в обратном вызове эффекта useHeight.

Обновление правой инверсии.

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

К сожалению, сообщество React еще не установило четкого различия между состоянием и эффектом.

Мы можем попытаться дать удобную для рендеринга формулу для хуков React в соответствии с концепцией наслоения State/Effect:

let handler = useProducer(consumer, options)


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

Возьмите useHeight в качестве примера, чтобы проверить полезность приведенной выше формулы.

2. Реагировать на реализацию

Функции, которые мы хотим реализовать, следующие:

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

то есть более тонкий контроль:

1) контрольный мониторинг/не мониторинг;

2) Контролируйте объем мониторинга и реагируйте только на те требования рендеринга, которые соответствуют требованиям.

Функции следующие:

Моя реализация кода повторяется от низкого уровня к высокому уровню.

Сначала реализуйте useResizeObserver, низкоуровневую адаптацию к dom api.

Возвращает 3 функции управления:

1) Триггер решает, какой элемент отслеживать;

2) включить запуск мониторинга;

3) отключить отключает мониторинг;

Идея реализации useResizeObserver отличается от того, что вы делали раньше: он не возвращает состояние и не вызывает повторный рендеринг, а вместо этого вызывает callback(target) для демонстрации эффекта изменения размера.

Затем мы реализуем useHeight на основе useResizeObserver, сужаем фокус наблюдения до offsetHeight и предоставляем новый метод getCurrentHeight.

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

При использовании в useHeight(onHeightResizeEffect) синхронизируйте currentHeight с setHeight по мере необходимости.

Определите, какой элемент следует отслеживать с помощьюObserver.trigger, и предоставьте функции управления, такие как enable/disable/getCurrentHeight, мониторинг с помощью useEffect и планирование различных элементов управления, когда это необходимо.

Выше показана удобная для рендеринга и точно контролируемая версия React-Hooks.

Демонстрационный адрес react-resize-observer

Код может быть немного длиннее, чем в версиях Svelte и Vue, но эта идея реализации State/Effect является общей и применимой в Vue.

Следующая демонстрация, основанная на той же концепции, использует Rxjs, Vue и собственный JS для достижения той же функции.

3. Реализация Rxjs

Реализуйте версию use-height для rxjs. Также поддерживаются: 1) переключатель триггера; 2) переключатель включения/выключения; 3) в состоянии включения высота фильтрующей части не реагирует.

Функции следующие:

Сначала реализуйте изменяемый размер, адаптируйте низкоуровневый API-интерфейс dom к наблюдаемой версии rxjs и используйте ранее адаптированный хуками реакции useResizeObserver.

Затем реализуйте onHeightChange, инвертируйте управление через тему, switchMap реализуйте переключение и верните четыре поля состояния $, триггер, включение, отключение.

вернуть состояние здесьскорее, чемreacthooksверсия принятаconsumerПотому что,stateВ отличие от версии с реактивными хуками, которая принимает потребителей, потому что состояниеВместо состояния у него есть потребитель в подписке (потребитель). То же самое и в природе.

Потребляйте данные через subscribe(state$) и фильтруйте/преобразовывайте/передавайте потоки данных через операторы rxjs. В других наблюдаемых потоках данных вызовите метод управления в обработчике, отключите/включите/триггер.

Демонстрационный адрес rxjs-resize-observer

Затем реализуйте версию use-height для vue/reactivity. Идея та же, что и в версии с реактивными хуками и в версии с rxjs.

В-четвертых, реализация Vue

Сначала реализуйте функцию, которая адаптирует низкоуровневый API resize-observer к реактивному состоянию vue.

Определяем smallReactive, слушаем изменения в state.trigger, реализуем функцию переключения resize-observer и отправляем цель в onResize.

Реализуйте другую функцию onHeightChange, расширьте ResizableState до HeightChangeState, добавьте поле состояния, чтобы включить/отключить переключатель, и добавьте поле высоты.

Вышеприведенное выполняет комбинацию двух эффектов:

1) Сопоставьте эффект onResize с state.height в соответствии с option.fiter;

2) Синхронизируйте state.trigger с resizeState.trigger

onHeightChange используется следующим образом:

onHeightChange определяет привязки эффекта состояния, но не указывает, какой элемент прослушивать и как использовать данные.

Определите, кого слушать, назначив state.trigger.

Используйте эффекты, чтобы решить, как потреблять.

Демонстрационный адрес vue-resize-observer

Функция выглядит следующим образом:

Внимательные студенты могли обнаружить, что приведенный выше код Vue использует только пакет @vue/reactivity и не использует код, связанный с представлением vue.

Верно.

vue/reactivity сам по себе достаточно мощен, чтобы реализовать множество функций независимо друг от друга. Подробнее читайте в статье «Демистификация наиболее потенциальных API-интерфейсов Vue-3.0».

Вот новое направление прикладного потенциала.

5. Режим State-Effect-Bindings в Vue

Vue/reactivity может реализовать шаблон привязки реактивного эффекта, который можно резюмировать как реактивный ({args, return}) и эффект.

Все функции имеют параметры args и возвращаемые значения, это можно сделать, сопоставив их с реактивным состоянием.Когда установлено state.args=, эффект выполняется повторно, а результат сопоставляется обратно с state.returned.

Этот режим очень удобен для фронтенд-разработчиков, потому что большая часть dom API такая.

elem.style.color = 'red', запускает эффект рендеринга и синхронизирует результат с calculatedStyle(elem).style.

Вернемся к vue-resize-observer, приведенный выше режим соответствует:

State.trigger resizable на самом деле является параметром ResizeObserver.observe.Его возвращаемое значение определяется как сам elem, который не соответствует условиям vue watch.Поэтому из поля state.target он становится обратным вызовом эффекта onresize.

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

Эффект изменения высоты onHeightChange можно синхронизировать с state.height, поэтому мы отменяем обратный вызов эффекта.

Операции улучшения, такие как фильтр, могут быть расширены для улучшения детального управления эффектом -> синхронизация состояния, а также может быть расширена дополнительная информация, такая как state.status.

Когда все приложение vue создаетсяшаблон привязки состояний-эффектовДля сборки в идеале в конце будет автоматически сформировано большое состояние приложения, и все состояние приложения будет автоматически настраиваемым.

appState.menu.status = 'on' открывает меню.

appState.loading.text = 'xxx' показывает загрузку.

effect(() => appState.menu.status) прослушивает изменения меню.

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

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

Например, resizable предоставляет только state.target, а onHeightChange расширяет {height, status} и другие состояния на этой основе.

6. Нативная JS-реализация: нет рамки в руках, рамка в сердце

Когда мы понимаем, что проблема не что иное, как постоянное булькание state-effect-bindings, есть ли react-hooks, есть ли rxjs, есть ли vue-реактивность, то не надо.

Сначала реализуйте Resizable, примите параметр объекта и верните объект. Параметр объекта — посетитель/потребитель, а возвращаемый объект — обработчик.

Реализуйте HeightChange на основе Resizable, принимайте параметры объекта с большим количеством полей и возвращайте объекты с большим количеством методов.

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

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

демонстрационный адрес vanilla-resize-observer

Функция выглядит следующим образом:

Хотя нативный JS также доступен, react-hooks, rxjs и vue-reactivity также полезны.Здесь мы в основном демонстрируем универсальность концепции наложения состояний/эффектов в разработке пользовательского интерфейса.

Суммировать

Как и выше, мы продемонстрировали кодовую реализацию реакции, rxjs, vue и vanilla-js для достижения той же функции в рамках концепции многоуровневого состояния/эффекта.

Мы можем добавить концепцию управления эффектами на основе концепции управления состояниями.

Как я уже говорил в вопросе и ответе:

1) Когда сложность данных вашего проекта очень низкая, вы можете использовать состояние компонента, которое поставляется с реакцией

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

3) Когда сложность данных вашего проекта высока, mobx + react — хороший выбор.

4) Когда сложность данных вашего проекта высока, redux + react может помочь вам сохранить предсказуемость и ремонтопригодность с менее крутой кривой спуска. Все изменения состояния нормализуются действиями.

5) Когда сложность данных вашего проекта очень высока, а источники данных очень сложны, rxjs может помочь вам нормализовать все входные данные в наблюдаемые/потоковые данные, которые можно обрабатывать унифицированным способом.

Идея на самом деле очень проста:

1) Когда изменения пользовательского интерфейса очень сложны, используйте нормализацию компонентов, то есть View-Management

2) Когда изменения состояния сложны, используйте нормализацию действия/состояния, то есть State-Management.

3) Когда ввод данных очень сложный, нормализуйте его с помощью таких концепций, как rxjs/observable, то есть управление эффектами.

Произвольные задачи, если они достаточно общие и сложные, стоит абстрагироваться от специализированных механизмов.

Управление эффектами не очень процветает в экосистеме внешнего интерфейса с открытым исходным кодом, и это направление, в котором каждый может работать. Не только rxjs может управлять эффектами, но и vue/reactivity и react-hooks, и даже нативный JS может быть написан на голом языке, ожидая, пока все обнаружат.

В частности, фронтенд-сообщество может работать в следующих направлениях:

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

2) На основе концепций vue/reactivity и State-Effect-Bindings реализован фреймворк управления состоянием/эффектом (который также можно использовать без фреймворка vue view).

3) На основе rxjs и режима State-Effect-Observeable реализовать структуру управления состоянием/эффектом (можно использовать с любой структурой представления).

Надеюсь, что некоторые студенты смогут создать успешные кейсы в указанном выше направлении~

Источник цитирования:

[0] «Демистификация наиболее потенциального API Vue-3.0»

Tickets.WeChat.QQ.com/Yes?__Author=M za…

[1] Сравнение высоты использования между react и svelte

Twitter.com/Adam RAC KIS/…

[2] Авторская реализация Vue use-height

Twitter.com/Yuyuxiao/Это он…