> Как мне вам показать пример компонента с бизнес-логикой, которая в нем не сидит?
Ну так в том и дело. Я хочу увидеть, как будет выглядеть ваше решение в полноценном виде, с отдельной моделью.
> Надеюсь, что вы когда-нибудь дойдет до осознания, что jsx — это не разметка страницы, а формальный язык описания интерфейса.
Ну так и HTML — это формальный язык описания интерфейса.
> Вы как дите малое. Я вам про реальную проблему — наличие лишней обертки и возможность решить эту пробему на реакте и невозможность решить ее на ангуляре, а вы за синтаксис.
Так наследованием — все работает. Но вам это не нравится по синтаксическим соображениям.
> В первом ангуляре были только директивы. Которые «выглядели» как компоненты. С сохранением нужной гибкости: не нужна обертка — ставим replace.
Еще раз — вы говорите что раз есть реплейс, то атрибут-директивы не нужны. Но они там были. Почему?
> jsx — это не какой-то шаблон, который «живет отдельно от модели», это описание композиции функций — посмотрите выхлоп бабеля в конце концов уже.
Шаблоны ангуляра — это тоже описание композиции функций. Они компилируются так же как jsx в чистый джаваскрипт, там хтмля не остается. Ну и на пехепе тоже композиции функций писали :)
> Я вроде показал — создание Dynamic на лету.
Ну вы же создаете ее все равно в промежуточном виде. Как сразу в jsx? Или он превратился в тыкву тут?
> Вы ерунду-то не несите, очевидно же, что задача решена, а вам обидно.
Нет, не решена. Сделайте, чтобы работало с любой компонентной.
> А еще лучше — приведите конкретный пример для переноса на реакт.
> Ну подкиньте хоть пример, что вам накатать. А то я придумать не могу, у меня в компонентах бизнес-логика не сидит как-то.
Ну так а я о чем? Не сидит. Вот вы и покажите мне реальный пример, где бизнес-логика в компонентах не сидит, а не кнопки--однострочники :)
> Вы до сих пор живете внутри html-шаблона, тогда как jsx !== html.
Слушайте, ну на эту маркетинговую чепуху ведутся только те, кто на php ни разу не писал. Называть-то вы это можете как угодно, но суть явления от смены нвзвания не меняется, и jsx выглядит в точности как генерация портянок html коды из пыха, то самое прокидывание пропсов кстати — оно и в php было, там же тоже функциями генерили, render-методы у классов :)
> Принцип этот не оттуда
Именно оттуда :)
Это сделано для того, чтобы логика клиент-сайда максимально напоминала логику сервер-сайда. Именно сервер-сайд у вас работает по принципы state -> view. Ну а вдом — да, деталь реализации, необходимая для того, чтобы «писать на клиенте как на сервере».
> Да, но директивы можно было делать и по имени тэга, и именно replace я имел в виду.
Вы говорите, что директивы-атрибуты нужны как костыль из-за отсутствия replace. В первом ангуляре было и то и то. Что-то не сходится?
> Вы не правильно используете синтаксис — интерфейс компонента не объявляет аттрибут blink.
Я ж вам показываю ангуляроподобный синтаксис. А задача — сделать как в ангуляре, все верно.
> Еще раз вернемся к jsx !== html — это более высокий уровень абстракции.
Да наоборот все. Шаблоны — это ДСЛ, а в jsx вы пишете по факту на хост-языке.
> Я могу вам на лету собрать мигающий компонент из немигающего — это будет правильно, и по сути тоже самое. Синтаксис другой только.
Ну хорошо, пусть другой. Но объявлять отдельно блинкающуюся компоненту я не хочу, я хочу сразу в jsxe как-то это сделать. Как будет ваш код без объявления промежуточного AlreadyBlinkingComponent выглядеть? Что если у меня таких директив не одна, а 10? мне 2^10=1024 таких компонент объявлять? Кроме того, ваша компонента изначально позволяет менять background-color, то есть заточена работать с blinked. Я хочу возможность работы с любой компонентной, даже с той, у которой background-color в пропсах нет.
> Вы про стейт компонента или что? Ну выносите операции над стейтом в функции вида state => state и передавайте их в setState.
Ну вы, пожалуйста, продемонстрируйте, что получится. А то однострочники меня уже давно не возбуждают, я для этого слишком стар, извините уж.
> Аттрибутные директивы введены только как костыль для решения проблемы лишних оберток.
Все несколько наоборот. Это реакт сам по себе был придуман как костыль для портирования сервер-сайд логики с php на клиент. Оттуда jsx (старательно мимикрирующий в своей семантике под php), оттуда принцип «перерендерить все» (именно это происходит при классическом запросе браузера к серверу — сервер вам генерит каждый раз всю страницу заново), отсюда vdom (чтобы этот подход не слишком сильно тормозил), изоляция стейта да и все остальное.
> Если бы компоненты ангуляра могли рендерить другие в качестве хоста (к слову, как это было в первом)
Так в первом ангуляре тоже были аттрибут-селекторы, несмотря на наличие replace.
> Но раз уж просите —
Вы просто лишний аргумент добавили, я же совсем не то просил. Сделайте аналог аттрибут-директивы, которая будет каждую секунду, например, менять background хоста: черный-красный-черный-красный и т.д.
Чтобы я мог вместо <Component/> написать <Component blink/> — и оно у меня мигает.
> Когда в то же время достигается совершенно тот же эффект.
Так я же процитирую вас:
> к решению задачи с кнопками _в таком же виде, как она решена на реакте_.
Вот и я вас прошу не достичь «такого же эффекта», а решить в том же виде, как на ангуляре. Просто потому, что я «изначально так поставил задачу».
> Но если вам совсем уж надо — есть ref, findDOMNode и все вытекающие.
Ну нет, это не по правилам. Вы же не разрешали писать кастомные декораторы? Значит, никаких refов с findDOMNode — это все ненативно, бяка и т.д., какие вы там аргументы приводили против подобных решений.
> Сравните, пожалуйста, примеры выше еще разок.
Да сравнивал, они практически построчно совпадают (я о варианте с наследованием).
> Сохранив при этом компонуемость в том виде, в котором мне нужно.
Ну как же вы сохраните? Вид и модель будут отдельно? Будут.
> Я не вижу ни одной причины гоняться за мнимым отделением шаблона от его компонента
А вы в реакте всю логику суете прям в компонент, таким вот невнятным ворохом? Ну тогда ясно все.
> Вопрос дизайна и подхода — текущий не дает мне нужной гибкости, которую дает реакт.
Как не дает, если гибкость решения на ангуляре наоборот _выше_? Все, что можно на реакте — можно легко повторить на ангуляре. Но вот если я начну просить ангуляровские вещи повторить на реакте — у вас это просто вообще не выйдет, тут сработает аналог правила Гринспена :)
> как простейшие в реакте вещи сделать с огородом костылей в 20 раз сложнее на ангуляре
Ну у вас проблема в том, что вы не понимаете архитектуры ангуляра и называете «костылями» пару строчек вполне идеоматического кода. Вы пытаетесь задаунгрейдить ангуляр до примитивного уровня реакта, где просто ничего нет. Это знаете, как сравнивать какой-нибудь ЯВУ с ассемблером. Приходит человек и говорит: «а вот я хочу параметр через стек передать для вызова подпрограммы. В ассемблере пишу две строчки и все работает — push/pop, а как у вас, в java/c#/javascript/etc? Ой какой ужас в 20 раз сложнее». Примерно так для меня ваши тезисы выглядят, если честно.
> ут идеально бы подошел интерфейс, но инжектор не умеет инжектить компоненты по интерфейсу.
Вообще умеет. Брать токен по типу — это лишь стандартное поведение, можно в аргументах в конструкторе сделать (@Inject(token) host: InterfaceComponent) и в хост заинжектится нужный токен, полностью будет как-то: ( Host() Inject(token) host: InterfaceComponent) (@Host() ограничивает инжектор, с-но, хостом), ну и в самой хост-компоненте надо зарегистрировать провайдер для соответствующего токена.
> HostListener, как и HostBinding, работает только с нативными ивентами на дом-ноде хоста.
Нет, он со всеми работает, я специально проверил.
> Да, вот только мне явно нужно знать класс компонента, к которому я прицепляюсь.
Так вы уже определитесь — вам loaded не нужен (и тогда вы точно знаете класс) или нужен (тогда не знаете). Если класс неизвестен, то делается интерфейс, который компоненты, к которым можно подмешивать нужное поведение, реализуют, и хост инжектится потом по кастомному токену
raveclassic и, собственно, вы же можете поступить как в реакте — то есть написать ф-ю, которая принимает один класс (модель), и возвращает новый — с измененным поведением. Вам только надо будет явно связать эту модель со старым видом, и все:
const template = `<div><button>{{ name }}</button></div>`;
@Component({
selector: "my-button",
template: template,
})
export class MyButtonComponent {
@Input() name = "";
}
export function loaded(component: any) {
return class extends component {
name = "loaded";
};
}
@Component({
selector: "loaded-button",
template: template,
})
export class LoadedButtonComponent extends loaded(MyButtonComponent) {};
> Идеологически на уровне редьюсера стейт с одним и тем же промисом (даже ссылка та же) но в разных состояних — это 3 разных стейта, так как по сути описывают 3 разных состояния: pending, success, fail. Это же разные состояния? Разные.
Это состояние промиса. Зачем его тащить в стейт? ПРусть будет локлаьным для промиса.
> А тут бац, сессия сдохла — как это в редьюсере похендлить?
А как вы это хендлите вне редьюсера?
> Как вы синхронно отмотаете список экшенов, когда среди них есть асинхронные?
Среди них нет асинхронных. Любой экшн — это просто тип с пейлоадом.
> А там какая-то асинхронщина, которая другие экшены выбрасывает. А в оплоге они уже есть, упс.
Вот именно. Это проблема, когда у нас произвольные сайд-эффекты, но когда эффекты ограничены (например — исключительно спавном, возможно асинхронным, других экшенов), то они не оказывают влияния ни на стор, ни на ход рендера, по-этому мы можем просто мокнуть ф-ю, которая внутри редьюсера вызывает эффект, в x => {return;}, которая ничего не делает.
> Собственно undo/redo так и делается. Там не экшены применяются/отменяются, а просто заменяется весь стейт.
В этом случае редьюсеры не вызываются и вообще никаких проблем нет. Мотай себе стейт куда захочешь и как захочешь.
«Чистую» часть редьюсеров вы можете тестировать так же просто. а «Грязная»… ну она и в оригинальном редаксе была грязной, просто находилась не в редьюсерах.
Зачем проект? Просто пример.
> Ну и вы так и не сказали, решение чего.
Так пусть будет с теми же кнопками. Просто структурировано так, как это будет в реальности, на нормальных компонентах, с выделенной моделью.
> Это безобразие и перекочевало в головы пхп-шников, пришедших в первый ангуляр
Вот в ангуляре как раз в отличии от реакта от пхп ничего не было :)
То же двухсторонний биндинг — сугубо антипхпшная концепция.
> А мы помним про composition over inhertitance.
В этой имеется ввиду фразе не та композиция, которая функциональная.
> Вы можете себе представить что-то такое:
Вот хороший пример. В случае с ф-и я могу ф-ю прямо в коде использовать, без промежуточного объявления.
> Тогда я не понимаю, чем вам не нравится ref/findDOMNode.
Ну хорошо, пусть будет с рефом. Главное, чтобы работало.
Ну так в том и дело. Я хочу увидеть, как будет выглядеть ваше решение в полноценном виде, с отдельной моделью.
> Надеюсь, что вы когда-нибудь дойдет до осознания, что jsx — это не разметка страницы, а формальный язык описания интерфейса.
Ну так и HTML — это формальный язык описания интерфейса.
> Вы как дите малое. Я вам про реальную проблему — наличие лишней обертки и возможность решить эту пробему на реакте и невозможность решить ее на ангуляре, а вы за синтаксис.
Так наследованием — все работает. Но вам это не нравится по синтаксическим соображениям.
> В первом ангуляре были только директивы. Которые «выглядели» как компоненты. С сохранением нужной гибкости: не нужна обертка — ставим replace.
Еще раз — вы говорите что раз есть реплейс, то атрибут-директивы не нужны. Но они там были. Почему?
> jsx — это не какой-то шаблон, который «живет отдельно от модели», это описание композиции функций — посмотрите выхлоп бабеля в конце концов уже.
Шаблоны ангуляра — это тоже описание композиции функций. Они компилируются так же как jsx в чистый джаваскрипт, там хтмля не остается. Ну и на пехепе тоже композиции функций писали :)
> Я вроде показал — создание Dynamic на лету.
Ну вы же создаете ее все равно в промежуточном виде. Как сразу в jsx? Или он превратился в тыкву тут?
> Вы ерунду-то не несите, очевидно же, что задача решена, а вам обидно.
Нет, не решена. Сделайте, чтобы работало с любой компонентной.
> А еще лучше — приведите конкретный пример для переноса на реакт.
Ну так а я о чем? Не сидит. Вот вы и покажите мне реальный пример, где бизнес-логика в компонентах не сидит, а не кнопки--однострочники :)
> Вы до сих пор живете внутри html-шаблона, тогда как jsx !== html.
Слушайте, ну на эту маркетинговую чепуху ведутся только те, кто на php ни разу не писал. Называть-то вы это можете как угодно, но суть явления от смены нвзвания не меняется, и jsx выглядит в точности как генерация портянок html коды из пыха, то самое прокидывание пропсов кстати — оно и в php было, там же тоже функциями генерили, render-методы у классов :)
> Принцип этот не оттуда
Именно оттуда :)
Это сделано для того, чтобы логика клиент-сайда максимально напоминала логику сервер-сайда. Именно сервер-сайд у вас работает по принципы state -> view. Ну а вдом — да, деталь реализации, необходимая для того, чтобы «писать на клиенте как на сервере».
> Да, но директивы можно было делать и по имени тэга, и именно replace я имел в виду.
Вы говорите, что директивы-атрибуты нужны как костыль из-за отсутствия replace. В первом ангуляре было и то и то. Что-то не сходится?
> Вы не правильно используете синтаксис — интерфейс компонента не объявляет аттрибут blink.
Я ж вам показываю ангуляроподобный синтаксис. А задача — сделать как в ангуляре, все верно.
> Еще раз вернемся к jsx !== html — это более высокий уровень абстракции.
Да наоборот все. Шаблоны — это ДСЛ, а в jsx вы пишете по факту на хост-языке.
> Я могу вам на лету собрать мигающий компонент из немигающего — это будет правильно, и по сути тоже самое. Синтаксис другой только.
Ну хорошо, пусть другой. Но объявлять отдельно блинкающуюся компоненту я не хочу, я хочу сразу в jsxe как-то это сделать. Как будет ваш код без объявления промежуточного AlreadyBlinkingComponent выглядеть? Что если у меня таких директив не одна, а 10? мне 2^10=1024 таких компонент объявлять? Кроме того, ваша компонента изначально позволяет менять background-color, то есть заточена работать с blinked. Я хочу возможность работы с любой компонентной, даже с той, у которой background-color в пропсах нет.
Ну вы, пожалуйста, продемонстрируйте, что получится. А то однострочники меня уже давно не возбуждают, я для этого слишком стар, извините уж.
> Аттрибутные директивы введены только как костыль для решения проблемы лишних оберток.
Все несколько наоборот. Это реакт сам по себе был придуман как костыль для портирования сервер-сайд логики с php на клиент. Оттуда jsx (старательно мимикрирующий в своей семантике под php), оттуда принцип «перерендерить все» (именно это происходит при классическом запросе браузера к серверу — сервер вам генерит каждый раз всю страницу заново), отсюда vdom (чтобы этот подход не слишком сильно тормозил), изоляция стейта да и все остальное.
> Если бы компоненты ангуляра могли рендерить другие в качестве хоста (к слову, как это было в первом)
Так в первом ангуляре тоже были аттрибут-селекторы, несмотря на наличие replace.
> Но раз уж просите —
Вы просто лишний аргумент добавили, я же совсем не то просил. Сделайте аналог аттрибут-директивы, которая будет каждую секунду, например, менять background хоста: черный-красный-черный-красный и т.д.
Чтобы я мог вместо <Component/> написать <Component blink/> — и оно у меня мигает.
> Когда в то же время достигается совершенно тот же эффект.
Так я же процитирую вас:
> к решению задачи с кнопками _в таком же виде, как она решена на реакте_.
Вот и я вас прошу не достичь «такого же эффекта», а решить в том же виде, как на ангуляре. Просто потому, что я «изначально так поставил задачу».
> Но если вам совсем уж надо — есть ref, findDOMNode и все вытекающие.
Ну нет, это не по правилам. Вы же не разрешали писать кастомные декораторы? Значит, никаких refов с findDOMNode — это все ненативно, бяка и т.д., какие вы там аргументы приводили против подобных решений.
> Сравните, пожалуйста, примеры выше еще разок.
Да сравнивал, они практически построчно совпадают (я о варианте с наследованием).
вот рабочий вариант, целиком:
А вы только обертки над кнопками пишете? В реальном мире у большинства компонент есть нетривиальная логика.
> Я не понял, что вы имеет в виду. Можете пример на ангуляре, чтобы понятней было?
Ну attribute directive, мы же о них сейчас как раз говорили.
> Мало того, что вы на ангуляре не пришли к решению задачи с кнопками в таком же виде, как она решена на реакте.
С чего вы взяли, что она должна решаться _в таком же виде_? Главное, чтобы не сложнее, а в таком или не таком — уже не важно.
еще я мог в декларации провайдера напутать, я ее не помню, надо в доках смотреть
Ну а теперь перепишите это к нормальному виду, для полноценной задачи, чтобы бизнес-логика была вынесена в отдельный класс хотя бы.
> Если мне понадобиться вынести логику в «модель», я вынесу и буду принимать ее через props.
Ну так продемонстрируйте. На однострочниках-то все всегда хорошо :)
> А если еще дальше — я поставлю inversifyjs и буду инжектить ее прямо в компонент/контейнер. Все.
Ну так вы не стесняйтесь, продемонстрируйте то, о чем сейчас так лихо рассказали. Я же не так просто правило Гринспена вспомнил :)
> Ну давайте, жгите!
Давайте с чего-нибудь простого начнем. Сделайте мне аналог компоненты с селектором-атрибутом.
както так
Ну как же вы сохраните? Вид и модель будут отдельно? Будут.
> Я не вижу ни одной причины гоняться за мнимым отделением шаблона от его компонента
А вы в реакте всю логику суете прям в компонент, таким вот невнятным ворохом? Ну тогда ясно все.
> Вопрос дизайна и подхода — текущий не дает мне нужной гибкости, которую дает реакт.
Как не дает, если гибкость решения на ангуляре наоборот _выше_? Все, что можно на реакте — можно легко повторить на ангуляре. Но вот если я начну просить ангуляровские вещи повторить на реакте — у вас это просто вообще не выйдет, тут сработает аналог правила Гринспена :)
> как простейшие в реакте вещи сделать с огородом костылей в 20 раз сложнее на ангуляре
Ну у вас проблема в том, что вы не понимаете архитектуры ангуляра и называете «костылями» пару строчек вполне идеоматического кода. Вы пытаетесь задаунгрейдить ангуляр до примитивного уровня реакта, где просто ничего нет. Это знаете, как сравнивать какой-нибудь ЯВУ с ассемблером. Приходит человек и говорит: «а вот я хочу параметр через стек передать для вызова подпрограммы. В ассемблере пишу две строчки и все работает — push/pop, а как у вас, в java/c#/javascript/etc? Ой какой ужас в 20 раз сложнее». Примерно так для меня ваши тезисы выглядят, если честно.
Вообще умеет. Брать токен по типу — это лишь стандартное поведение, можно в аргументах в конструкторе сделать (@Inject(token) host: InterfaceComponent) и в хост заинжектится нужный токен, полностью будет как-то: ( Host() Inject(token) host: InterfaceComponent) (@Host() ограничивает инжектор, с-но, хостом), ну и в самой хост-компоненте надо зарегистрировать провайдер для соответствующего токена.
Нет, он со всеми работает, я специально проверил.
> Да, вот только мне явно нужно знать класс компонента, к которому я прицепляюсь.
Так вы уже определитесь — вам loaded не нужен (и тогда вы точно знаете класс) или нужен (тогда не знаете). Если класс неизвестен, то делается интерфейс, который компоненты, к которым можно подмешивать нужное поведение, реализуют, и хост инжектится потом по кастомному токену
Чтобы можно было подмешивать поведение к разным компонентам. А если этого не надо, то вообще не понятно, в чем была исходная проблема.
> Плюс у меня есть смутные подозрения, что, выносят темплейт из класса, мы теряем всяческую помощь IDE внутри этого темплейта.
В тайпскрипте уже сделали language-service, так что это не проблема теперь.
> Зачем должна, кому должна,
Человеческой архитектуре. В реакте-то вы все равно к той же схеме придете, так какая разница.
С декларативными эффектами она не грязная :)
Но оверхед от достижения этой декларативности кажется значительно превышающим какой-то один мок.
Это состояние промиса. Зачем его тащить в стейт? ПРусть будет локлаьным для промиса.
> А тут бац, сессия сдохла — как это в редьюсере похендлить?
А как вы это хендлите вне редьюсера?
> Как вы синхронно отмотаете список экшенов, когда среди них есть асинхронные?
Среди них нет асинхронных. Любой экшн — это просто тип с пейлоадом.
> А там какая-то асинхронщина, которая другие экшены выбрасывает. А в оплоге они уже есть, упс.
Вот именно. Это проблема, когда у нас произвольные сайд-эффекты, но когда эффекты ограничены (например — исключительно спавном, возможно асинхронным, других экшенов), то они не оказывают влияния ни на стор, ни на ход рендера, по-этому мы можем просто мокнуть ф-ю, которая внутри редьюсера вызывает эффект, в x => {return;}, которая ничего не делает.
> Собственно undo/redo так и делается. Там не экшены применяются/отменяются, а просто заменяется весь стейт.
В этом случае редьюсеры не вызываются и вообще никаких проблем нет. Мотай себе стейт куда захочешь и как захочешь.