Вкат не с нуля, но практических навыков мало, а из проектов - только один свёрстанный по макету более-менее адаптивный лендинг с двумя строками JS.
Есть посредственные знания HTML/CSS, чуть менее посредственное знание JS. Два-три дня назад начал разбираться с реактом, сегодня начну писать мувисёрчер)0 по туториалу.
https://www.youtube.com/watch?v=TOb1c39m64A
И добавил сразу же TS вместо JS, потому что, кажется, на чистом JS сейчас уже никто не пишет уже. В туториале этого не было, но там всего лишь надо было добавить пресет для Babel. И ещё StyleLint и ESLint (с гайдлайнами Airbnb) подключил.
Конечно, этот Webpack слишком муторный, всё вручную надо прописывать. Но create-react-app мне малость не нравится, мне кажется, он слишком много деталей скрывает. Да и, я думаю, теперь можно будет везде копировать все эти конфиги, которые сейчас написал (украл из туториала).
>потому что туда вкатитьсявроде должно быть проще, чем куда-либо ещё.
По какому критерию? Вкатунов тысячи, роадмап примерно как у всех.
Ни разу не слышал на двачах дельного совета. Скорее всего про фронт тоже пиздежь. Учи питон, как раз ты походу любитель одноглазых питончиков.
Python - это вроде в основном про бэкенд, ещё data science и machine learning. Я не вижу, как это может быть проще шлёпания сайтиков на реакте. И к тому же я не хочу сейчас с нуля учить новый ЯП.
Для цветов и отступов использую похожие наименования с числами 100, 200 и тд: для цветов от более бледных к более насыщенным (и дополнительное деление на neutral, primary, secondary), для отступов - от маленьких к большим.
Плюс именно CSS-свойств, а не просто SCSS-переменных в том, что можно писать медиа-запросы для CSS-свойств, чтобы адаптивно менять размер шрифтов и отступы на разных размерах экранов. Такой монструозный миксин специально написал для этого. Цвета, кстати, можно было и не делать CSS-свойствами, к ним я медиа-запросы вряд ли буду писать, но да ладно.
Минус в том, что IE 11 (который до сих пор not dead) не поддерживает CSS свойства, но меня это сейчас не сильно волнует. Не знаю, пишут ли так в реальном мире, но, мне кажется, это достаточно универсальный и удобный подход.
Как и конфиги вебпака, буду теперь копировать это от пет-проекта к пет-проекту.
> И добавил сразу же TS вместо JS, потому что, кажется, на чистом JS сейчас уже никто не пишет уже.
Не совсем. Я довольно много разных проектов сменил (с разного масштаба компаниях) и там как не придёшь, так "ой, ну мы сейчас переписываем всё на TS".
В общем, нет большой проблемы, чтобы учить TS и писать петы на нём, только помни, что в отличие от JS, у TS нет нормальной спеки и поломки в API относительно часто появляются.
> Вроде более-менее вспомнил что-то из SCSS. Сделал такой сетап.
Выглядит, конечно, сильно лучше, чем мешанина, но такой подход усложняет ведение проекта, особенно крупного. Всё это лучше разносить по доменам (DDD) или папкам компонентов.
> Минус в том, что IE 11 (который до сих пор not dead) не поддерживает CSS свойства, но меня это сейчас не сильно волнует.
Ещё поддерживают, к сожалению. Во многом в банках или [около]госах.
Вообще, молодец, но лучше бы тебе придумать более чёткий план, так ты сможешь быстрее развиваться ибо будешь понимать, в какую сторону тебе нужно расти.
> Скорее всего про фронт тоже пиздежь.
Не, тут прикол в том, что вкат чуть проще, но потом сложность всё равно сильно вырастет)
Фильмы вроде ищутся, но ещё надо будет разобраться, как доставать дополнительную информацию о них (режиссёра-постановщика, длительность, постеры в разрешении побольше). Локализацию, тёмную тему, анимации ещё, наверное, надо сделать. Но я пока что со стилями туплю очень сильно.
https://larsenwork.com/easing-gradients
https://www.npmjs.com/package/postcss-easing-gradients
Выглядит интересно, линейный градиент бывает очень плохо смотрится. Но, к сожалению, поддерживаемый синтаксис очень бедный: работает только для перехода между двумя цветами, хотелось бы больше.
Короче, так и не доделал ничего.
Не использую БЭМ для именования классов, он слишком душный, слишком длинные названия классов получаются. Для компонентов даю более-менее уникальные названия, для элементов внутри пишу короткие названия классов по типу "title" или "poster" и пишу для них селекторы по вложенности. Вроде бы так не делают, вообще не знаю, как в реакт приложениях со стилями обходятся.
Немного посильнее разбил всё по файлам и вроде дописал запросы к API, сейчас на скрине нету вручную вбитых данных.
Дизайн самой карточки я, кстати, украл откуда-то, но не копировал код.
Внезапно сильно раздулся файл, который делает все запросы, не знаю пока что, что с ним делать. Ещё не знаю, как быть с типами для JSON-объектов, которые отдаёт API. Наверное, вручную прописать эти типы придётся, потом сделаю и в целом почищу то, что написал сейчас.
Имена людей, к сожалению, все на английском.
Случайно укололся об то, что сделал array.forEach(async () => { ... }) внутри async функции. Внешняя функция, естественно, не ждала запросов внутри цикла, и всё ломалось, это нужно было либо переписать на for of, либо я ещё видел в интернете вариант смаппить массив array в массив async функций и сделать Promise.all().
Нарисовал SVG-звёздочки, закрашиваю их градиентом, сколько там рейтинг. Не уверен, зачем я это сделал, много времени потратил и мне не нравится результат. Раздражает, что в SVG похоже градиентам обязательно нужно давать уникальный на уровне страницы ID, пришлось прицепить lodash.uniqueId на градиент для каждой звёздочки.
https://standart.io
Нашёл такой сайт с вроде бесплатными SVG-иконками, выглядят неплохо и однородно.
Ещё этот сайт https://iconscout.com вроде нормальный, но там не все бесплатны, некоторые free with attribution.
Звёздочки выглядят плохо и пиксельно, когда они так сильно уменьшены, не знаю, как фиксить. Указать явно shapeRendering="geometricPrecision" не помогает, это, скорее всего, по умолчанию уже и так есть. Сама звёздочка в JSX написана. Интересно, что в SVG местами работают CSS свойства, по крайней мере можно ими раскрасить звёздочки, не будет проблем с тем, чтобы добавить тёмную тему.
Посмотрел немного, что такое styled components, выглядит как полнейший колхоз. Сейчас не буду уже, естественно под них ничего переделывать в муви сёрчере, попробую что-нибудь следующее потом с их использованием написать. Потому что это вроде популярный подход (смесить не только HTML и JS, но и CSS туда ещё впихнуть), нравится мне это или нет.
Из-за того, что на каждый фильм теперь дополнительно делаются два дополнительных запроса на то, чтобы достать режиссёра-постановщика, поиск заметно замедляется. Нужно будет потом, когда разберусь с более простыми вещами, попробовать в каком-то виде сделать ленивую подгрузку картинок и информации о фильме по мере того, как листаешь список. И чтобы на месте этих данных отображался какой-нибудь плейсхолдер с анимацией, наверное. Я видел, так делают вроде многие.
Ещё можно будет сделать, чтобы можно было сохранять фильмы в понравившиеся, чтобы приложение совсем уж голым не было.
Немного посильнее разбил всё по файлам и вроде дописал запросы к API, сейчас на скрине нету вручную вбитых данных.
Дизайн самой карточки я, кстати, украл откуда-то, но не копировал код.
Внезапно сильно раздулся файл, который делает все запросы, не знаю пока что, что с ним делать. Ещё не знаю, как быть с типами для JSON-объектов, которые отдаёт API. Наверное, вручную прописать эти типы придётся, потом сделаю и в целом почищу то, что написал сейчас.
Имена людей, к сожалению, все на английском.
Случайно укололся об то, что сделал array.forEach(async () => { ... }) внутри async функции. Внешняя функция, естественно, не ждала запросов внутри цикла, и всё ломалось, это нужно было либо переписать на for of, либо я ещё видел в интернете вариант смаппить массив array в массив async функций и сделать Promise.all().
Нарисовал SVG-звёздочки, закрашиваю их градиентом, сколько там рейтинг. Не уверен, зачем я это сделал, много времени потратил и мне не нравится результат. Раздражает, что в SVG похоже градиентам обязательно нужно давать уникальный на уровне страницы ID, пришлось прицепить lodash.uniqueId на градиент для каждой звёздочки.
https://standart.io
Нашёл такой сайт с вроде бесплатными SVG-иконками, выглядят неплохо и однородно.
Ещё этот сайт https://iconscout.com вроде нормальный, но там не все бесплатны, некоторые free with attribution.
Звёздочки выглядят плохо и пиксельно, когда они так сильно уменьшены, не знаю, как фиксить. Указать явно shapeRendering="geometricPrecision" не помогает, это, скорее всего, по умолчанию уже и так есть. Сама звёздочка в JSX написана. Интересно, что в SVG местами работают CSS свойства, по крайней мере можно ими раскрасить звёздочки, не будет проблем с тем, чтобы добавить тёмную тему.
Посмотрел немного, что такое styled components, выглядит как полнейший колхоз. Сейчас не буду уже, естественно под них ничего переделывать в муви сёрчере, попробую что-нибудь следующее потом с их использованием написать. Потому что это вроде популярный подход (смесить не только HTML и JS, но и CSS туда ещё впихнуть), нравится мне это или нет.
Из-за того, что на каждый фильм теперь дополнительно делаются два дополнительных запроса на то, чтобы достать режиссёра-постановщика, поиск заметно замедляется. Нужно будет потом, когда разберусь с более простыми вещами, попробовать в каком-то виде сделать ленивую подгрузку картинок и информации о фильме по мере того, как листаешь список. И чтобы на месте этих данных отображался какой-нибудь плейсхолдер с анимацией, наверное. Я видел, так делают вроде многие.
Ещё можно будет сделать, чтобы можно было сохранять фильмы в понравившиеся, чтобы приложение совсем уж голым не было.
>Всё это лучше разносить по доменам (DDD) или папкам компонентов.
Наверное. Хотя, мне кажется, особой разницы нет между тем, чтобы CSS лежал в папке компонента и тем, чтобы была отдельная папка css/components, в которой бы в кучу были свалены все стили для компонентов.
>придумать более чёткий план
Я не знаю, где его найти. Все роадмапы одинаково бесполезны, потому что перечисляют один и тот же очевидный список фреймворков и прочего. Просто буду что-то делать, наверное, смотреть фреймворки всякие.
Более-менее почистил код, дописал типы для JSON-объектов (только те свойства, которые использую я сам), немного разлепил гигантскую функцию, которая по строке-запросу возвращала список фильмов: теперь у меня есть async функции, которые повторяют API и возвращают Partial объекты (не у всех фильмов есть обложка, рейтинг и тд) с сырыми данными, и функция, которая, используя эти функции, возвращает список фильмов со всеми данными в одном месте.
Странно, что нет аналога ?? для truish значений, есть момент, где это бы пригодилось, но приходится писать тернарный оператор. && там не подойдёт из-за того, что пустая строка воспринимается как false.
Попробую теперь локализацию и переключение языка сделать, это вроде должно быть легко.
https://react.i18next.com/latest/using-with-hooks
Нашёл такой фреймворк, вроде популярный. Но у меня почему-то при переключении языка шрифт как будто на долю секунды меняется, причём это происходит только в первый раз при переключении. И на хроме, и на файрфоксе так. Не нашёл решение.
И почему-то <Trans> не хочет работать, в консоли выводится, что этот i18next не успел инициализироваться, хотя я вроде написал <Suspense> и он должен был подождать его. Но если дописать useTranslation(), то всё начинает нормально работать. Я не понимаю. Немного странным способом подключается этот фреймворк ещё...
Слишком много времени потратил на это, но вроде работает хотя бы как-то, по крайней мере в консоли ошибок и предупреждений не выдаёт, даже выбранный язык сохраняет в local storage сам, ну и ладно.
>Фронтенд сильно душит, мне не нравится, мне не интересно, ещё и сложно местами.
А потом тебе ещё и работать с этим придётся.
Ну а что мне ещё делать? В моих глазах это выглядит как единственный реалистичный вариант, куда можно в теории вкатиться. Да и меня бы любая работа душила, банально из-за того, что неё надо каждый день ходить, регулярно там чем-то заниматься.
А я, даже сейчас, после того, как намучился с тем фреймворком, не смог сегодня больше принудить себя продолжить делать муви сёрчер.
>Фронтенд сильно душит, мне не нравится, мне не интересно, ещё и сложно местами
>не смог сегодня больше принудить себя продолжить делать муви сёрчер.
>выглядит как единственный реалистичный вариант, куда можно в теории вкатиться
То, что я не смог продолжить делать муви сёрчер больше связано с тем, что я устал слишком рано сегодня. Не связано с фронтендом напрямую.
>>Фронтенд сильно душит, мне не нравится, мне не интересно, ещё и сложно местами
> я устал слишком рано сегодня. Не связано с фронтендом напрямую.
Что, не удобный вопрос?
Зубы кстати покажешь, в американской культуре белоснежная улыбка must have, а айти берёт тренды сам понимаешь откуда.
Я с таким настроем несколько раз пробовал вкатиться в разные вышки, дропал на первом году.
Сейчас тоже к фронту присматриваюсь..и тоже не очень-то мотивирует, когда вижу реальные предметы, с которыми придётся работать.
Но если ты отличник и умел превозмогать те вещи, которыми не нравится заниматься, то наверно у тебя получится.
Только учти, что фронт это не про фриланс по большей части.
Сделал немного всякой CSS мелочи, довольно мало: дописал переводы, научился делать анимации и сделал простенькую анимацию загрузки, доделал карточки, чтобы они нормально отображались на всех размерах экранов. Всё ещё плохо справляюсь с гридами и флексами и с CSS в целом, тривиальные задачи занимают много времени.
Я думаю, имеет смысл попробовать сверстать что-нибудь по макету или повторить дизайн какого-нибудь сайта. Видел такой сайт про последнее https://www.frontendpractice.com
Наткнулся на проблему: у меня есть <form>, внутри которого поле ввода названия фильма, кнопка поиска, и я хотел сгруппировать кнопку и поле визуально вместе с переключателем темы и языков, но не знаю, как это сделать без костылей и не засовывая переключатели внутрь <form>.
Кажется, сабгриды должны будут решить подобные проблемы: можно будет управлять положением не только непосредственных детей, но и более глубоких потомков. Но сабгриды до сих пор только эксклюзивно в Firefox. Пока что не знаю, как с этим справляться.
i18n - это, оказывается, internalization, так же, как a11y - это accessibility. А сам тот фреймворк назывался i18next.
Не понимаю, как обходиться с айдишками в реакте: нужно ли, чтобы айди элементов сохранялись между рендерами компонента? Просто функции, которые передаёшь дочерним компонентам, точно лучше в useCallback оборачивать, иначе может быть много лишних рендеров. Есть ли тут что-то подобное? Тут просто это и не пропс, это атрибут у реакт-элемента, не знаю, не нашёл ничего про это. Наверное, всё же нет смысла использовать useRef тут.
Наткнулся на проблему с тем, что иногда нужно задать какое-то CSS-правило через JS (фоновую картинку), а потом переопределить его в CSS (убрать эту картинку в медиа-запросе). Видимо, единственное решение - писать !important. Тут как раз styled components выглядели бы лучше, потому что все стили и так в JS.
Случайно узнал про фреймворк axios, он похож на fetch, но интерфейс местами лучше сделан: можно прямо в функцию get-запроса передавать параметры запроса (с fetch приходится заранее формировать URL со всеми параметрами), ещё он сразу возвращает JSON, а не response, который надо потом в JSON преобразовывать. Вроде есть более фундаментальные отличия, но я не разбирался.
Мне кажется, сочетание кастомных CSS свойств с fallback значениями для них, заданными через SCSS переменные - это лучшее сочетание, чтобы писать переиспользуемые CSS-компоненты с возможностью в рантайме ещё и поменять то, как выглядит компонент.
Сделал немного всякой CSS мелочи, довольно мало: дописал переводы, научился делать анимации и сделал простенькую анимацию загрузки, доделал карточки, чтобы они нормально отображались на всех размерах экранов. Всё ещё плохо справляюсь с гридами и флексами и с CSS в целом, тривиальные задачи занимают много времени.
Я думаю, имеет смысл попробовать сверстать что-нибудь по макету или повторить дизайн какого-нибудь сайта. Видел такой сайт про последнее https://www.frontendpractice.com
Наткнулся на проблему: у меня есть <form>, внутри которого поле ввода названия фильма, кнопка поиска, и я хотел сгруппировать кнопку и поле визуально вместе с переключателем темы и языков, но не знаю, как это сделать без костылей и не засовывая переключатели внутрь <form>.
Кажется, сабгриды должны будут решить подобные проблемы: можно будет управлять положением не только непосредственных детей, но и более глубоких потомков. Но сабгриды до сих пор только эксклюзивно в Firefox. Пока что не знаю, как с этим справляться.
i18n - это, оказывается, internalization, так же, как a11y - это accessibility. А сам тот фреймворк назывался i18next.
Не понимаю, как обходиться с айдишками в реакте: нужно ли, чтобы айди элементов сохранялись между рендерами компонента? Просто функции, которые передаёшь дочерним компонентам, точно лучше в useCallback оборачивать, иначе может быть много лишних рендеров. Есть ли тут что-то подобное? Тут просто это и не пропс, это атрибут у реакт-элемента, не знаю, не нашёл ничего про это. Наверное, всё же нет смысла использовать useRef тут.
Наткнулся на проблему с тем, что иногда нужно задать какое-то CSS-правило через JS (фоновую картинку), а потом переопределить его в CSS (убрать эту картинку в медиа-запросе). Видимо, единственное решение - писать !important. Тут как раз styled components выглядели бы лучше, потому что все стили и так в JS.
Случайно узнал про фреймворк axios, он похож на fetch, но интерфейс местами лучше сделан: можно прямо в функцию get-запроса передавать параметры запроса (с fetch приходится заранее формировать URL со всеми параметрами), ещё он сразу возвращает JSON, а не response, который надо потом в JSON преобразовывать. Вроде есть более фундаментальные отличия, но я не разбирался.
Мне кажется, сочетание кастомных CSS свойств с fallback значениями для них, заданными через SCSS переменные - это лучшее сочетание, чтобы писать переиспользуемые CSS-компоненты с возможностью в рантайме ещё и поменять то, как выглядит компонент.
Мне кажется, из всех моих сверстников, кто хотел вкатиться, уже по крайней мере получил опыт работы, не хочу лишний раз задумываться о том, что пытаюсь влезть в уходящий поезд.
>белоснежная улыбка must have
Я, кстати, вполне допускаю, что даже, если дойду до момента, когда буду ходить по собеседованиям, мне могут отказывать не в последнюю очередь из-за того, что внешность и поведение сильно неприятные или нерасполагающие к себе.
>>545477
>не очень-то мотивирует, когда вижу реальные предметы, с которыми придётся работать
Мне скорее просто не хочется работать никем.
>умел превозмогать те вещи, которыми не нравится заниматься
Не про меня, скорее наоборот.
>фронт это не про фриланс по большей части
Да, я даже не надеюсь на работу из дома.
На пике ты?
Да мне тоже не хочется. С другой стороны, альтернатива только писать тексты за гречку.
Можно ещё пенсию по шизе получать, но пока как-то не выходит.
>фронт это не про фриланс по большей части
>Да, я даже не надеюсь на работу из дома.
Но из дома это же не обязательно фриланс)
>Кажется, сабгриды должны будут решить подобные проблемы
Нет, тут больше подошло бы display: contents для <form>, случайно узнал о нём только что. Он сделает так, что потомки <form> воспринимаются как непосредственные дети родителя <form>, в общем, как будто <form> не существует.
https://caniuse.com/css-display-contents
Поддержка намного лучше, чем у сабгридов (там написано, что в сафари плохая поддержка но оба упомянутых бага вроде уже закрыты, а на a11y вроде всем в реальном мире всё равно, как я понимаю). И он тут намного лучше по смыслу подходит.
Но сабгриды всё ещё могут быть полезны для того https://www.youtube.com/watch?v=IIQa9f0REtM чтобы разметка дочерних элементов была выровнена по линиям родительского грида.
https://www.youtube.com/watch?v=R7aHcgIeATE
Тут немного странный пример, таблица же лучше подошла бы, но не знаю, можно ли стилизовать её так же, чтобы столбцы так отдельно стояли. Но вроде в любом случае, если семантически нужна таблица, то лучше использовать именно её.
https://ishoudinireadyyet.com
https://houdini.glitch.me
https://youtu.be/x0nD8VUScmc
Случайно узнал про Houdini, это набор API, с помощью которого можно расширять CSS. Пока что частично доступно только в chromium-based браузерах. Не знаю, получит ли это всё когда-нибудь более широкую поддержку и использует ли это кто-либо сейчас.
https://youtu.be/FtOvR1tKs1Y
Я изначально просто повёлся на то, с каким упоением она рассказывала про этот Houdini, а он, оказывается, спустя два года, всё ещё далеко не везде поддерживается (конкретно в Firefox). И я подозреваю, что это так и останется обскурной фишкой хромиум браузеров, про которую все забудут совсем скоро (и до этого почти никто не знал). Хотя я сам бы хотел повсеместную поддержку Typed CSSOM и CSS Properties and Values API.
https://developers.google.com/web/updates/2018/01/paintapi
Там есть painting API, которым можно рисовать на элементах так же, как по канвасу. Точнее можно написать на JS функцию, которая генерирует картинку, которую можно в CSS подставить, например, как фоновую картинку, как border-image, как mask-image для элемента. Не знаю, насколько это полезно. Разве что в случаях, когда нужно именно процедурно, в зависимости от параметров что-то делать. И чтобы сэкономить на количестве элементов в доме.
>There are many use cases for paint worklets, some of them more obvious than others. One of the more obvious ones is using paint worklet to reduce the size of your DOM. Oftentimes, elements are added purely to create embellishments using CSS. For example, in Material Design Lite the button with the ripple effect contains 2 additional <span> elements to implement the ripple itself. If you have a lot of buttons, this can add up to quite a number of DOM elements and can lead to degraded performance on mobile. If you implement the ripple effect using paint worklet instead, you end up with 0 additional elements and just one paint worklet. Additionally, you have something that is much easier to customize and parameterize.
>Another upside of using paint worklet is that — in most scenarios — a solution using paint worklet is small in terms of bytes. Of course, there is a trade-off: your paint code will run whenever the canvas’s size or any of the parameters change. So if your code is complex and takes long it might introduce jank. Chrome is working on moving paint worklets off the main thread so that even long-running paint worklets don’t affect the responsiveness of the main thread.
https://developers.google.com/web/updates/2018/03/cssom
CSS typed object model выглядит полезнее: он позволяет в JS доставать значения CSS свойств не как обычные строки, а как специальные объекты, в которых внутри есть само значение и единица измерения. Ещё арифметические функции и конвертация между величинами есть.
https://css-tricks.com/exploring-property-and-its-animating-powers
Ещё сделали типизацию для кастомных CSS свойств: можно либо в JS определить, либо через @property в CSS. Позволяет анимировать кастомные свойства в том числе.
Ещё layout API для кастомных лэйаутов и animation worklet.
https://developers.google.com/web/updates/2018/10/animation-worklet
Вроде им можно будет с хорошей производительностью делать анимации потенциально в отдельном потоке, привязанные к каким-то рантайм значениям (например, к скроллу или другим свойствам какого-то элемента) плюс возможность делать stateful анимации. Это я уже даже приблизительно не смотрел, всё равно совсем плохая поддержка: даже в хроме только в canary вроде бы, я не проверял сам.
https://ishoudinireadyyet.com
https://houdini.glitch.me
https://youtu.be/x0nD8VUScmc
Случайно узнал про Houdini, это набор API, с помощью которого можно расширять CSS. Пока что частично доступно только в chromium-based браузерах. Не знаю, получит ли это всё когда-нибудь более широкую поддержку и использует ли это кто-либо сейчас.
https://youtu.be/FtOvR1tKs1Y
Я изначально просто повёлся на то, с каким упоением она рассказывала про этот Houdini, а он, оказывается, спустя два года, всё ещё далеко не везде поддерживается (конкретно в Firefox). И я подозреваю, что это так и останется обскурной фишкой хромиум браузеров, про которую все забудут совсем скоро (и до этого почти никто не знал). Хотя я сам бы хотел повсеместную поддержку Typed CSSOM и CSS Properties and Values API.
https://developers.google.com/web/updates/2018/01/paintapi
Там есть painting API, которым можно рисовать на элементах так же, как по канвасу. Точнее можно написать на JS функцию, которая генерирует картинку, которую можно в CSS подставить, например, как фоновую картинку, как border-image, как mask-image для элемента. Не знаю, насколько это полезно. Разве что в случаях, когда нужно именно процедурно, в зависимости от параметров что-то делать. И чтобы сэкономить на количестве элементов в доме.
>There are many use cases for paint worklets, some of them more obvious than others. One of the more obvious ones is using paint worklet to reduce the size of your DOM. Oftentimes, elements are added purely to create embellishments using CSS. For example, in Material Design Lite the button with the ripple effect contains 2 additional <span> elements to implement the ripple itself. If you have a lot of buttons, this can add up to quite a number of DOM elements and can lead to degraded performance on mobile. If you implement the ripple effect using paint worklet instead, you end up with 0 additional elements and just one paint worklet. Additionally, you have something that is much easier to customize and parameterize.
>Another upside of using paint worklet is that — in most scenarios — a solution using paint worklet is small in terms of bytes. Of course, there is a trade-off: your paint code will run whenever the canvas’s size or any of the parameters change. So if your code is complex and takes long it might introduce jank. Chrome is working on moving paint worklets off the main thread so that even long-running paint worklets don’t affect the responsiveness of the main thread.
https://developers.google.com/web/updates/2018/03/cssom
CSS typed object model выглядит полезнее: он позволяет в JS доставать значения CSS свойств не как обычные строки, а как специальные объекты, в которых внутри есть само значение и единица измерения. Ещё арифметические функции и конвертация между величинами есть.
https://css-tricks.com/exploring-property-and-its-animating-powers
Ещё сделали типизацию для кастомных CSS свойств: можно либо в JS определить, либо через @property в CSS. Позволяет анимировать кастомные свойства в том числе.
Ещё layout API для кастомных лэйаутов и animation worklet.
https://developers.google.com/web/updates/2018/10/animation-worklet
Вроде им можно будет с хорошей производительностью делать анимации потенциально в отдельном потоке, привязанные к каким-то рантайм значениям (например, к скроллу или другим свойствам какого-то элемента) плюс возможность делать stateful анимации. Это я уже даже приблизительно не смотрел, всё равно совсем плохая поддержка: даже в хроме только в canary вроде бы, я не проверял сам.
Я думаю, очевидно, что я прокрастинирую листанием бесполезных статей и просмотром видео вместо того, чтобы делать что-то более осмысленное.
Да у него ещё и перхоть.
1692x1044, 0:35
>Да никакого прогресса. Как имбецил смотрю в монитор, а все знания которые не используются они тут же стираются. Как говорят евреи если твои знания выше дел твоих, то бесполезны твои знания. Вот это мой случай как раз.
Двачую.
https://css-tricks.com/striking-a-balance-between-native-and-custom-select-elements
Интересный подход, чтобы сделать кастомный <select>. На телефонах (touch девайсах) будет отображаться нативный <select> (он удобнее, потому что список опций большим модальным окном открывает), также, если сфокусироваться с клавиатуры, то отобразится нативный, чтобы не нужно было реализовывать ещё и кастомную клавиатурную навигацию. А когда мышкой кликаешь, то работает кастомный. Плюс a11y почти за бесплатно, на которую всем плевать, впрочем.
Это мне было нужно из-за того, что внутрь <option> нельзя вообще ничего, кроме текста добавлять, а я хотел просто в опциях селекта языка нарисовать флажки стран. Через эмодзи не получилось: в 10 винде не поддерживаются эмодзи флагов.
Только этот селект и сделал сегодня.
Стрелочку сделал через mask-image, потому что если добавить SVG как фоновую картинку, то кастомные CSS свойства внутри не работают и нельзя поменять (адекватным способом, CSS фильтры не в счёт) цвет картинки.
Вебпак начал ругаться, что у меня энтри поинт (main.js + main.css) стал слишком большим (>250кб вроде). Не знаю, как уменьшить, я и так сделал:
last 1 version
not IE 11
> 1%
Когда-нибудь потом, возможно, придётся посмотреть, как разбивать код на несколько кусков в вебпаке.
:has - гениальный псевдокласс, который абсолютно нигде не поддерживается. Можно было бы использовать в связке с + и ~, чтобы выбрать элемент, за которым что-то следует. Я у себя хотел использовать, чтобы поменять аутлайн при нажатии на мой кастомный селект: .selected-option:has(+ .options.visible).
- переключатель светлой / тёмной тем
- отменять предыдущие запросы перед тем, как делать новый (сейчас, если сделать два подряд, то отработают оба)
- загрузка следующей страницы с результатами, когда долистываешь до конца (сейчас я только одну страницу загружаю)
- ленивая подгрузка картинок и данных о фильмах (загружать только четыре первых фильма, остальные подгружать, если до них долистываешь, так же, пачками по 4 штуки), на месте недостающих картинок и текста отображать какую-нибудь загрузочную анимацию (на видео так быстро загрузилось, потому что браузер уже закешировал все запросы, на деле он значительно дольше грузит)
- добавить возможность добавлять в избранное и смотреть список избранных фильмов, сохранять его в local storage
- анимация появления карточек: чтобы они всплывали с немного рандомной задержкой, какая-то анимация на hover карточки по типу такой (но гораздо менее заметная)
https://codepen.io/technokami/pen/abojmZa
- местами пофиксить HTML (я забыл, что карточки лучше делать через <article>), местами пофиксить CSS (недостающий хавер на селекте по крайней мере)
Это, наверное, минимум, чтобы получилось что-то адекватное, что не стыдно кому-то показать. Выглядит внешне оно плохо, конечно, я изначально не искал никакого готового дизайна, но уже не буду переделывать.
>>543892 (OP)
> посредственное знание JS. Два-три дня назад начал разбираться с реактом
Звучит неочень. Лучше бы сначала чистый жс добил.
> мувисёрчер
По Буре?
>>546121
> Мне кажется, без предыдущего опыта работы найти работу на удалёнке невозможно
Возможно, почему нет? Главное ищи удаленку и не принимай офферы на РАБоту в офисе. У меня в конторе есть люди, которые почти наверняка удалённо стартанули нельзя ж быть настолько нулевыми, при наличии какого-то прошлого опыта.
>Лучше бы сначала чистый жс добил.
Я не вижу смысла этого делать, лучше буду разбираться по мере надобности. Например, хочу сделать, чтобы подгрузка страниц была, когда скроллишь => гуглю intersection observer.
>По Буре?
Делаю запросы к API TMDB. Буры же про картинки вроде.
>Возможно, почему нет?
Просто такое ощущение, что вряд ли есть доверие к рандому без опыта работы и без образования.
Вроде это может быть полезно, если пишешь на винде что-то, что ещё и под линуксом должно работать. Наоборот (сидеть в VSCode на линуксе с подключённой виндовой VM) тоже можно, но я подозреваю, что винда под линуксом будет работать хуже, чем WSL. А WSL теперь даже линуксовые приложения с GUI может запускать. Сам WSL, кажется, ещё часто используется, чтобы запускать линуксовые докер-контейнеры под виндой. В случае с вебом это, видимо, про бэкенд в основном.
То есть мне никак это не нужно и я зря потратил время.
> Делаю запросы к API TMDB. Буры же про картинки вроде.
Я про говнокурс Юрия Буры, по которому куча людей уже мувики сделала.
До этого просто main.scss делал @use папки со стилями для компонентов. С модулями вроде действительно удобнее, потому что стили компонентов будут теперь локальными для них, и даже автодополнение для названий классов работает (если доустановить плагин). Правда теперь не знаю, везде ли использовать camelCase для именования CSS классов или только в CSS модулях. Или в CSS-модулях тоже kebab-case и использовать styles['class-name'] (выглядит малость громоздко, но склоняюсь всё же к этому варианту).
Единственное, не понял, как дебажить такие стили, наверное, в dev билдах нужно настроить, чтобы были человеческие имена классов, а не хеши. (Сорс мапы работают, но в коде всё равно хеши отображаются.)
Кстати, автодополнение для конфигов вебпака, stylelint и других тоже, оказывается, можно заставить работать, я не додумался прописать @type {import('webpack').Configuration} перед module.exports.
Ещё надо бы заюзать вот это https://github.com/entwicklerstube/babel-plugin-root-import чтобы перестать мучиться с относительными путями...
Но вся эта рутина очень сильно душит, как и фронт в целом, просто не могу заставить себя даже начать монотонно переписывать классы и импорты.
Нет, я свой начинал делать оглядываясь на рандомный туториал с ютуба, сейчас сам продолжаю доделывать всякое.
> Но вся эта рутина очень сильно душит, как и фронт в целом, просто не могу заставить себя даже начать монотонно переписывать классы и импорты.
Потому что пора уже работу искать, живые таски интересней делать
Я не думаю, что я сейчас готов работать где-либо, я хотел как минимум ещё доделать этот мувисёрчер, посмотреть дальше про реакт, redux (или mobx), styled components и ещё какие-нибудь фреймворки, что-нибудь поверстать (сейчас с этим очень туго, много туплю) и сделать ещё один пет с каким-нибудь простеньким бэком на ноде.
Хотя я не знаю точно, какие требования там, но вёрстку, реакт + какой-нибудь стейт менеджмент фреймворк всё же как минимум мне стоит досмотреть, я думаю.
Ты изниоткуда делаешь вывод, что именно на реакт устроишься работать, хотя есть другие фреймворки лучше реакта, плюс если ты в пердях, то есть цмски и почти нет фреймворков.
Вряд-ли тебе дадут со старта что-то сложнее вёрстки и лёгких скриптов. Вряд-ли будешь делать что-то с нуля сразу - каркас будет, а внутри уже на js надо орудовать.
> доделать этот мувисёрчер, посмотреть дальше про реакт, redux (или mobx), styled components
> сделать ещё один пет с каким-нибудь простеньким бэком на ноде.
Чтобы потом попасть на проект, где бэк на пхп или ноде, но тебе только фронт достанется , а фронт на vue.
Я не знаю, может, ты и прав, но мне в любом случае стрёмно вкатываться сейчас в работу.
> всё же сделать папки для компонентов, в которых .tsx + .scss [+ ресурсы?].
Ну здрасьте, а я что говорил постами выше?))
Он прав. Чего стрёмного? Ты сейчас боишься непонятно чего. Сходи на пару собесов, потрясись там от волнения (классика для джунов), а после поймёшь, по фитбеку, что тебе нужно учить и всё.
Ты просто не представляешь сколько людей туго соображающих занимают должности мидлов/синьоров, у тебя судя по всему думалка-то хорошая, просто тебе нужно не тупить и, как бы это странно не звучало, послушать анонов в двача и пойти на собес.
Ну и базу подучить, а не на реакты налегать, ибо это то, на чём все эти реакты работают.
> Ты изниоткуда делаешь вывод, что именно на реакт устроишься работать, хотя есть другие фреймворки
Если идти на реакт, то как раз будешь с ним работать)) Опробовал на себе, полёт нормальный.
Я не знал про CSS modules: с ними действительно есть смысл так делать. До них у меня все CSS классы компонентов были в глобальном скоупе по сути, поэтому не было особо разницы, куда класть файлы.
>>547719
Ну не хочу я сейчас. Когда созрею, тогда и пойду.
>Ну и базу подучить, а не на реакты налегать
Не понимаю, что конкретно ты имеешь в виду под базой. Из learn.javascript.ru, судя по оглавлению, я знаю практически всё из первой части и почти ничего из остальных двух.
События в браузере (сложнее клика по кнопке или отправки формы), drag'n'drop, определение размеров / положения элементов и скролла внутри браузера, mutation и intersection обзёрверы, прокси-объекты, встроенная интернационализация, какие-то продвинутые вещи про работу с сетью, веб-сокеты, веб-компоненты, shadow DOM, сложные регулярки (со всякими look ahead и look behind), работа с файлами и бинарными данными, теги для шаблонных строк.
Это всё я не знаю. Плюс плохо помню названия методов строк, мапов, сетов, приходится их гуглить, если использую.
И я не знаю, есть ли смысл прямо намеренно в этом всём разбираться просто, чтобы знать. Потому что я же забуду без использования на практике. Слишком специфичные вещи.
> Ну не хочу я сейчас. Когда созрею, тогда и пойду.
РАБотать или собеседоваться? Если первое, то имеет смысл все-таки ходить на собесы. На них можно обосраться с глобальным объектом и запомнить его хорошо, например.
> События в браузере (сложнее клика по кнопке или отправки формы), drag'n'drop, определение размеров / положения элементов и скролла внутри браузера, mutation и intersection обзёрверы, прокси-объекты, встроенная интернационализация, какие-то продвинутые вещи про работу с сетью, веб-сокеты, веб-компоненты, shadow DOM, сложные регулярки (со всякими look ahead и look behind), работа с файлами и бинарными данными, теги для шаблонных строк.
Это всё на работе изучается, по мере поступления задач. При этом половина не встретится. Вторая и третья главы learnjavascript, это справочник, не нужно это подряд читать.
> И я не знаю, есть ли смысл прямо намеренно в этом всём разбираться
Нет смысла.
> Потому что я же забуду без использования на практике
Я уже первую часть забыл почти всю, не смогу красиво рассказать, что такое ивент луп может быть, потому что никогда и не знал как и половину первой части, просто интуитивное понимание есть и его хватает, как он работает, асинками могу пользоваться, но рассказать про них не смогу нормально и тд.
Пора работу искать, в общем, становиться рабом системы, жить в режиме дом-работа-дом-кладбище, становиться мёртвым внутри, выгорать - ты не качнешься до мидла, сидя дома, а для получения работы уже достаточно скилов. Тестовое на реактохолопа гораздо легче, чем мувик сделать.
Ну даа, я понял, что ходить по собеседованиям нужно уже сейчас, потому что энивей мне будут с большой вероятностью отказывать, буду ли я даже подходить на 100% по требованиям или буду таким, какой сейчас. И что сейчас, сидя дома, я по сути просто трачу время и не будет выигрыша, если я сейчас ещё немного дома повкатываюсь и только потом пойду на собеседования.
Листая вакансии, действительно попадаются те, в которых требования ограничиваются максимум реактом, и пара стажировок с совсем минимальными требованиями. Но всё же довольно мало, как мне показалось.
Ещё показалось, что много фулстак вакансий с PHP бэком, чуть реже node.js. Я искал на hh.ru, введя в поиске "javascript" и отфильтровав по опыту работы "нет опыта", вроде так наиобльший охват того, что мне нужно, получается. Просто там поиск всратый какой-то, много нерелевантных результатов выдаёт.
А если поставить опыт "1-3 года", то внезапно сразу появляется гораздо больше вакансий с требованием по сути только реакта и умения верстать. То есть совсем нулёвые джуны никому не нужны, что, наверное, ожидаемо. И действительно, наверное, несильно важно, насколько я сейчас глубоко разбираюсь в реакте и знаю ли redux/mobx: я всё равно на большинство вакансий без опыта не подхожу.
До этого, если честно, я вакансии не листал ни разу, потому что было страшно, что увижу то же самое, что на дваче в тредах про лопнувший айти-пузырь, и не найду ничего, где бы я проходил по требованиям. Ну а я и не нашёл. Почти.
В общем, я так думаю тогда, что в течение завтрашнего дня доделаю свой поиск фильмов хотя бы в каком-то виде (сейчас он реально неюзабельный, там приходится ждать, пока выполнятся штук 15 запросов прежде, чем выведется список фильмов, это нужно пофиксить). Чтобы хотя бы его можно было показать и фильмы не грузились полминуты. На следующий день попробую откликнуться куда-нибудь, где минимальные требования.
import ComponentName from '@components/ComponentName';
Полистал вакансии, более внимательно посмотрел на фронтенд роадмапу, понял, что в моём случае она мало имеет общего с реальностью, ну я уже говорил об этом выше. Вакансии без опыта либо имеют довольно мало требований (и их самих не очень много), либо много или то, в чём я не разбираюсь даже близко (бэкенд). Поэтому смысла сейчас сидеть и по роадмапе прямо со всеми этими фреймворками, нодой, фреймворками под ноду, PWA, web components разбираться - нету, это едва ли сделает меня более подходящим кандидатом, судя по всему.
Тошнит и подкашиваются ноги только об одной мысли, что придётся разговаривать с кем-то, а это же на работе постоянно делают. И там надо сидеть каждый день, по 9 часов, ещё и заниматься чем-то продуктивным. Я абсолютно не представляю себя на этом месте, у меня язык заплетается и я забываю слова. Я ещё и не умею почти ничего, даже этот несчастный поиск фильмов до сих пор не доделал.
Я не хочу работать, но и убивать себя мне не хочется. Я никогда не смогу перелезть через подоконник или вогнать нож в руку поглубже, да и не хочу я ничего такого делать. Но это всё как будто подразумевается как один из вариантов, которые тебе предоставлены. И это всё мои проблемы, никому это не интересно.
скок лет? у тебя же уже почти получилось. можешь свой код скинуть? залей на Гин или куда-нить
> А если поставить опыт "1-3 года"
Лучше их тоже включай в поиск, если в текстовом описании вакансии не упоминается год опыта.
> с совсем минимальными требованиями. Но всё же довольно мало, как мне показалось.
Честные требования, видимо. Я проходил по вакансиям с "нормальными" требованиями, считая, что не совсем им соответствую, а потом видел, как после меня совсем нулевые проходили по той же вакансии - например без опыта работы с фреймворком, который указан в вакансии, без опыта в год, который указан был и даже без нормальных знаний вёрстки. Но их взяли.
> До этого, если честно, я вакансии не листал ни разу
Я так обнаружил, что на реакт в моем городе 2 вакансии и не вкатился в реакт. А время потратил на него.
>>548296
> ещё и заниматься чем-то продуктивным
В хороший день это часов 5, может 6, если задача интересная. Ищи сразу удаленку - шансы есть, гарантирую. На удаленке проще, всё общение, это созвоны, на 1-2 часа в день, где самому говорить нужно минут 10.
> Я не хочу работать, но и убивать себя мне не хочется
Хорошая постановка проблемы, жизненная. Вообще можно 4 часа в день ставку взять - естественно, когда опыт будет, чтоб по деньгам норм было. 4 часа это ж изи, а зп всё-равно сильно выше медианной по стране.
> Я ещё и не умею почти ничего
Научись одной очень важной вещи, перед тем, как начинать работать - научись поиску по проекту. Не знаю почему, но очень многие вкатаны, конечно не могут найти что-то в коде. Есть блок с вёрсткой, они не могут его найти. Им не приходит в голову, что вообще-то всё, что нужно для поиска, у них есть - берёшь класс блока, ищешь, где встречается, находишь. Но нет, люди вообще ничего найти не могут, им проще сказать, что этого блока нет, хоть он и отображается. Или метод найти не могут, зная, что он делает и понимая, что в названии это отражено.
Да это же реально омерзительный трап. Зачем ты такое постишь?
ОП, слушай его. Поиск по проекту это то, про что обычно никто не говорит потому что просто даже не думают, что это может стать проблемой.
> что меня по сути вынуждают это делать
Кто тебя вынуждает?
>Я бы вообще никаким кандидатом не хотел быть
Чего хочешь ты?
>в течение завтрашнего дня доделаю свой поиск фильмов
>На следующий день попробую откликнуться куда-нибудь
Ничего из этого не делал. Не знаю, когда буду.
Посмотрел про event loop
https://www.youtube.com/watch?v=8aGhZQkoFbQ
https://learn.javascript.ru/event-loop
я до этого не знал про это. И что .then, .catch, .finally (микротаски) у промисов тоже асинхронно выполняются, но отличие от макротасков в том, что перед рендером очередь микротасков очищается полностью перед рендером, так что они выполняются в одной и той же среде. Алсо это объясняет, почему я видел в чужом коде, что в функции, которая отрисовывает кадр анимации requestAnimationFrame вызывалась в самом начале.
Восполнил пробел, связанный с методами Object. Всякие способы создания объектов (create, assign, fromEntries), способы достать список свойств (keys, values, entries, getOwnPropertyDescriptors, for in), freeze, seal, preventExtensions.
И что значат параметры в дескрипторе свойства: writable, configurable - можно ли удалить или изменить дескриптор свойства, enumerable - будет ли видно при переборе через for in, keys, values, entries.
Это мне никак не пригодится, но это объясняет, почему у меня может не получиться поменять свойства какого-то объекта. И почему, например, в for in для массива не выводятся его методы, а только его значения по индексам.
Ещё для меня было открытием, что Array.prototype.sort сортирует массив так, как будто это массив строк. То есть [1, 2, 10, 20] он отсортирует как [1, 10, 2, 20].
https://www.typescriptlang.org/docs/handbook/mixins.html
https://fettblog.eu/typescript-interface-constructor-pattern
https://dmitripavlutin.com/typescript-covariance-contravariance
Ещё посмотрел про оставшиеся хуки в реакте: useReducer и useContext. Первый вроде может выглядеть лучше, чем useState, если нужно за один раз поменять несколько кусков внутри сложного состояния. И ещё лучше это вроде должно выглядеть вместе с этим фреймворком https://immerjs.github.io/immer/example-setstate потому что в хуках в отличие от setState в классовых компонентах, нужно возвращать полное новое состояние.
Оказывается, в ESLint есть плагин для реакт хуков, который предупреждает, если ты в useEffect, useCallback, useMemo не указал полный список зависимостей для них.
>в течение завтрашнего дня доделаю свой поиск фильмов
>На следующий день попробую откликнуться куда-нибудь
Ничего из этого не делал. Не знаю, когда буду.
Посмотрел про event loop
https://www.youtube.com/watch?v=8aGhZQkoFbQ
https://learn.javascript.ru/event-loop
я до этого не знал про это. И что .then, .catch, .finally (микротаски) у промисов тоже асинхронно выполняются, но отличие от макротасков в том, что перед рендером очередь микротасков очищается полностью перед рендером, так что они выполняются в одной и той же среде. Алсо это объясняет, почему я видел в чужом коде, что в функции, которая отрисовывает кадр анимации requestAnimationFrame вызывалась в самом начале.
Восполнил пробел, связанный с методами Object. Всякие способы создания объектов (create, assign, fromEntries), способы достать список свойств (keys, values, entries, getOwnPropertyDescriptors, for in), freeze, seal, preventExtensions.
И что значат параметры в дескрипторе свойства: writable, configurable - можно ли удалить или изменить дескриптор свойства, enumerable - будет ли видно при переборе через for in, keys, values, entries.
Это мне никак не пригодится, но это объясняет, почему у меня может не получиться поменять свойства какого-то объекта. И почему, например, в for in для массива не выводятся его методы, а только его значения по индексам.
Ещё для меня было открытием, что Array.prototype.sort сортирует массив так, как будто это массив строк. То есть [1, 2, 10, 20] он отсортирует как [1, 10, 2, 20].
https://www.typescriptlang.org/docs/handbook/mixins.html
https://fettblog.eu/typescript-interface-constructor-pattern
https://dmitripavlutin.com/typescript-covariance-contravariance
Ещё посмотрел про оставшиеся хуки в реакте: useReducer и useContext. Первый вроде может выглядеть лучше, чем useState, если нужно за один раз поменять несколько кусков внутри сложного состояния. И ещё лучше это вроде должно выглядеть вместе с этим фреймворком https://immerjs.github.io/immer/example-setstate потому что в хуках в отличие от setState в классовых компонентах, нужно возвращать полное новое состояние.
Оказывается, в ESLint есть плагин для реакт хуков, который предупреждает, если ты в useEffect, useCallback, useMemo не указал полный список зависимостей для них.
Ну тогда ты всю оставшуюся жизнь будешь страдать. Сначала с пердолингом тебя жиэсом, а потом работой. Что тебе мешает послать всех нахуй и делать то, что ты хочешь?
> Что тебе мешает послать всех нахуй и делать то, что ты хочешь?
Желание что-то кушать, носить одежду, иметь доступ к электричеству, воде, интернету?
Полистал задания на регулярки в codewars, чувствую себя немного более уверенно с ними. Именованные группы - очень хорошо в плане читаемости, я про них не знал. И не знал, что можно референсить группы внутри самой регулярки через \1-\9 или даже \k<name>, чтобы сматчить несколько повторений одного и того же.
По возрастающей в плане навороченности:
- RegExp.test - проверить, матчится ли строка
- String.search - найти позицию матча
- String.match - список матчей (если с флагом g), либо один матч со списком групп (если без флага g) без именованных
- RegExp.exec - каждый вызов возвращает следующий матч со всеми группами (в том числе именованными), за счёт того, что изменяет lastIndex (откуда начинать искать) у регулярки
- String.matchAll - то же самое, только iterable, но передаваемую регулярку не изменяет
Меня всегда напрягало такое обилие способов применить регулярку к строке и я всё время путался: когда какой применять.
И ещё я не знал, что String.replace может референсить захваченные группы, и там можно ещё передать функцию, которая делает замену, но ей немного неудобно пользоваться из-за того, что у неё много аргументов, а не один объект-аргумент, который можно было бы деструктурировать. String.replaceAll, кстати, то же самое, что и просто replace, единственное отличие - выбрасывает исключение, если передать регулярку без флага g.
На всякий случай почитал про то, что такое strict mode. До этого забивал на это, потому что всё равно писал код только в модулях, где он включён по умолчанию. В общем, самые значимые (и это почти все, на самом деле) отличия:
- если вызвать функцию без биндинга, то this будет undefined, а не глобальным объектом
- если написать присваивание необъявленной переменной, то выпадет исключение вместо присвоения свойству глобального объекта с этим именем (причём не имеет значения, это происходит внутри какой-то функции или нет)
- присваивания non-writable полям, попытки удалить non-configurable свойства, попытки задать значения свойств у примитивных типов и подобные вещи выбрасывают исключения
- eval и arguments нельзя использовать для названий своих переменных (то есть function test(...arguments) выбросит ошибку), плюс ещё несколько слов зарезервировано на будущее
- изменение arguments и самих аргументов не синхронизировано (вот как раз из-за этого в ESLint есть правило no-param-reassign)
- with запрещено, но я про него до этого и не знал
- всё, что объявлено внутри eval, за его границы не протекает
Полистал задания на регулярки в codewars, чувствую себя немного более уверенно с ними. Именованные группы - очень хорошо в плане читаемости, я про них не знал. И не знал, что можно референсить группы внутри самой регулярки через \1-\9 или даже \k<name>, чтобы сматчить несколько повторений одного и того же.
По возрастающей в плане навороченности:
- RegExp.test - проверить, матчится ли строка
- String.search - найти позицию матча
- String.match - список матчей (если с флагом g), либо один матч со списком групп (если без флага g) без именованных
- RegExp.exec - каждый вызов возвращает следующий матч со всеми группами (в том числе именованными), за счёт того, что изменяет lastIndex (откуда начинать искать) у регулярки
- String.matchAll - то же самое, только iterable, но передаваемую регулярку не изменяет
Меня всегда напрягало такое обилие способов применить регулярку к строке и я всё время путался: когда какой применять.
И ещё я не знал, что String.replace может референсить захваченные группы, и там можно ещё передать функцию, которая делает замену, но ей немного неудобно пользоваться из-за того, что у неё много аргументов, а не один объект-аргумент, который можно было бы деструктурировать. String.replaceAll, кстати, то же самое, что и просто replace, единственное отличие - выбрасывает исключение, если передать регулярку без флага g.
На всякий случай почитал про то, что такое strict mode. До этого забивал на это, потому что всё равно писал код только в модулях, где он включён по умолчанию. В общем, самые значимые (и это почти все, на самом деле) отличия:
- если вызвать функцию без биндинга, то this будет undefined, а не глобальным объектом
- если написать присваивание необъявленной переменной, то выпадет исключение вместо присвоения свойству глобального объекта с этим именем (причём не имеет значения, это происходит внутри какой-то функции или нет)
- присваивания non-writable полям, попытки удалить non-configurable свойства, попытки задать значения свойств у примитивных типов и подобные вещи выбрасывают исключения
- eval и arguments нельзя использовать для названий своих переменных (то есть function test(...arguments) выбросит ошибку), плюс ещё несколько слов зарезервировано на будущее
- изменение arguments и самих аргументов не синхронизировано (вот как раз из-за этого в ESLint есть правило no-param-reassign)
- with запрещено, но я про него до этого и не знал
- всё, что объявлено внутри eval, за его границы не протекает
Одежда особо не важна. Я не помню, когда последний раз покупал что-то из одежды. Просто одно и то же ношу.
https://github.com/pugjs/pug-loader/issues/75#issuecomment-404650894
Короче, этот вебпак - походу просто сборник каких-то лагучих плагинов, написанных рандомами, половина которых частично устарели в контексте актуальной версии вебпака. Это последний раз, когда я сидел и пытался что-то настроить в вебпаке больше 5 минут, в следующий раз просто запущу вместо него Parcel. Просто зря время потратил на какой-то бред.
Ладно, скорее всего, я не прав и не понимаю, как он работает, но, если честно, мне всё равно.
> Просто зря время потратил на какой-то бред.
Так и есть. На работе то уже будет настроенный вебпак, если он в принципе будет на проекте. Клонируешь репозиторий, качаешь зависимости, профит, если не компилируется, спрашиваешь у тимлида, почему так - и зачем тогда знать вебпак вкатану?
Хочешь потрогать паг - используй бойлерплейт для него любой, который под твои желания подходит.
Зачем тебе это? В тред выше уже запостили картинку с распределением возрастов пограмистов, если ты к этому подводишь.
>>550493
>зачем тогда знать вебпак вкатану?
Что хочу, то и делаю, отвали.
И проблема не в том, что я не могу что-то в вебпаке настроить, а в том, что сам плагин для пага в вебпаке забагованный и не поддерживается разрабом. Ничего не изменится, если я скачаю чей-либо чужой вебпак бойлерплейт, который использует тот же самый плагин, а более вероятно придётся ещё пердолиться с тем, что нода или нпм неправильной версии и ничего не устанавливается.
Я бы мог попробовать gulp ещё, но мне лень.
Флоаты (очевидно, в контексте обтекания текстом / инлайн элементами, 2021 уже ведь).
Вместо clearfix есть более удобный display: flow-root, который заставляет родителя вмещать плавающие элементы (но что конкретно он делает, я не понял). На плавающий элемент можно повесить shape-outside, чтобы задать форму, по которой текст будет обтекать его, можно делать всякие странные вещи https://codepen.io/anonanon123/pen/jOLRZWE Чтобы сделать обтекание и слева, и справа, оба флоата в разметке должны идти перед обтекаемым элементом.
Позиционирование.
Static - дефолтное позиционирование в нормальном потоке. Relative - можно сдвинуть элемент относительно того, где он бы находился в нормальном потоке. Absolute - полностью убирает элемент из потока и позиционирует его относительно ближайшего не-static позиционированного предка. Fixed - относительно вьюпорта. Sticky - прилипает при скролле к вьюпорту (становится fixed), нужно обязательно указать какой-нибудь top/bottom/right/left. Кстати, центрировать position: absolute можно и не через трансформы, а margin: auto + inset: 0 (шортхенд для top/bottom/right/left).
Stacking context.
https://tiffanybbrown.com/2015/09/css-stacking-contexts-wtf
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index
Флексбоксы.
По поперечной оси элементы по умолчанию растягиваются (либо align-content/items/self). Распределение пространства для элементов по основной оси происходит в несколько этапов: сначала всем им назначается размер flex-basis (либо width / height, если он не задан, либо вроде max-content, если и они не заданы) минус бордеры, паддинги и марджины, то есть только контент. Потом делается перенос строк (если есть flex-wrap). Если после этого в строках не хватает места, то элементы ужимаются в соответствии с flex-shrink не сильнее, чем до min-content. При этом там такая формула, что степень ужатия зависит и от flex-shrink (чем больше, тем сильнее), и от размера элементов (большие элементы сжимаются сильнее, чем маленькие). А если есть свободное место, то оно распределяется просто с коэффициентами flex-grow. После этого всего применяются автоматические marginы и justify-content, если всё же свободное место осталось.
>размер flex-basis минус бордеры, паддинги и марджины, то есть только контент
Это объясняет, почему отличающиеся марджины, паддинги и бордеры ломают соотношения размеров флекс элементов. Что flex: 1 1 0 (то же самое, что flex: 1), что flex: 1 1 100% - не будут гарантировать одинаковых колонок в этом случае. Потому что во флексах при распределении размеров они просто выбрасываются из-за этого, что их всё равно нельзя сузить, например. Алсо большой min-content (длинные слова, например) могут ломать соотношения из-за того, что shrink ограничен min-contentом, но тут можно min-width: 0 выставить (и у тебя всё переполнится).
Видео про это https://youtu.be/fm3dSg4cxRI
https://codepen.io/anonanon123/pen/GRvLdWO
Вот пример, у него скопировал. Изначально выставил flex-basis на 1000px, но вычисления (пикрил девтулзы в Firefox) всё равно для 890px = 1000px - 5px - 5px (бордеры) - 50px - 50px (паддинги). И border-box не влияет на это поведение никак.
Это всё можно обойти, если обернуть каждый флекс-элемент, чтобы паддинги, марджины и бордеры входили в контент флекс-элемента, но гораздо проще использовать гриды, они подходят тут гораздо лучше.
order по умолчанию имеет значение 0.
flex-basis работает как универсальный размер вдоль главной оси.
flex-wrap: wrap-reverse просто меняет направление поперечной оси. Для управления направлениями обоих осей есть шортхенд flex-flow.
align-content влияет на распределение пространства между строками + их положение, тогда как align-items определяет положение элементов внутри строки, я так для себя это понимаю.
align-что-то - это про поперечную ось, justify-content - это про главную ось. В гридах похожие свойства, но там align-что-то - это всегда про вертикальную ось, а justify-что-то - всегда про горизонтальную. И почему-то неинтуитивно первой во всех сокращённых свойствах (по типу place-items) сначала указывается значение для вертикальной (align-что-то) оси.
Гриды.
Удобны, когда элементы выровнены по сетке друг относительно друга. Можно задать явно все строки и столбцы и назначить каждому элементу своё место в этой сетке, а можно использовать автоматически генерируемые строки и колонки.
У гридов очень много шортхендов, вот этот самый монструозный:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Grid_Template_Areas#grid-template
И ещё больше QoL фич, в частности неявное именование линий и областей, которыми, скорее всего, никто даже не пользуется:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Layout_using_Named_Grid_Lines
fr - fractional units - про распределение места.
Про auto:
>As a maximum represents the largest max-content size of the items in that track.
>As a minimum represents the largest minimum size of items in that track (specified by the min-width/min-height of the items). This is often, though not always, the min-content size.
>If used outside of minmax() notation, auto represents the range between the minimum and maxium described above. This behaves similarly to minmax(min-content,max-content) in most cases.
>Note: auto track sizes (and only auto track sizes) can be stretched by the align-content and justify-content properties. Therefore by default, an auto sized track will take up any remaining space in the grid container.
https://codepen.io/anonanon123/pen/abyxKvW
Про то, что auto = minmax(min-content, max-content) - это неправда, скорее auto = minmax(auto, auto). И он немного странно ведёт себя: в присутствии fr среди других размеров треков действительно похож на minmax(min-content, max-content). Но если есть только auto, то вроде как свободное именно от контента (не просто свободное место, как с fr) распределяется поровну между всеми auto грид-треками аналогично тому, что делает margin-left+right auto в флексбоксах. А сам margin auto в гридах выравнивает элемент только внутри грид клетки (эквивалентен place-self).
minmax - задаёт минимальный и максимальный размеры, но на самом деле умеет чуть больше. Самый частый паттерн использования - minmax(фикс. размер, 1fr), чтобы ограничить минимальный размер и растянуть по возможности. Очень часто юзается в сочетании с самым топовым правилом:
grid-template-columns: repeat(auto-fit, minmax(фикс. размер, 1fr));
repeat, кстати, работает и с повтором группы из нескольких строк / столбцов.
https://css-tricks.com/auto-sizing-columns-css-grid-auto-fill-vs-auto-fit
Различия auto-fit и auto-fill, второй бесполезный, как мне кажется.
Когда треков в гриде не хватает, генерируются автоматические, размер которых задаётся через grid-auto-columns/rows, а направление - через grid-auto-flow. Причём есть дополнительные значения row-dense и column-dense, которые нарушают порядок, но стараются как можно плотнее упаковать элементы.
Селекторы.
Чтобы выбрать n-ный элемент, использовать nth-of-type вместо nth-child, потому что nth-child выбирает элемент только, если он n-ый по счёту потомок среди всех потомков. Но с nth-of-type тоже нужно быть аккуратным, потому что если не указать тип элемента в селекторе: .child:nth-of-type(2), то выберутся вторые элементы с классом child для каждого типа элемента (для каждого HTML тега).
:nth-child(n+a):nth-child(-n+b) - интересный паттерн, чтобы выбрать потомков от a-ого по счёту, то b-ого.
:is позволяет меньше печатать и им можно делать что-то вроде декартова произведения селекторов, но его специфичность = максимально специфичному селектору внутри. Из-за этого будет сложнее переписать некоторые CSS правила, которые заданы через :is. :where - то же самое, что и :is, только не добавляет специфичность совсем. https://developer.mozilla.org/en-US/docs/Web/CSS/:where#examples Ещё статья в блоге гугла https://web.dev/css-is-and-where
Всякие странности CSS.
- box-sizing: border-box вместо дефолтного content-box - ставить по умолчанию всегда и везде, просто потому что, желательно вместе с margin: 0 и padding: 0. Всё же я не понимаю, как можно пользоваться этими дефолтными браузерными стилями. Хотя я слышал, что многим больше нравится normalize, а не reset всего.
- Горизонтальные внешние отступы схлопываются, но вертикальные - нет. Более того, вертикальные могут протечь из родителя, если у последнего нет бордера или паддинга.
- Между инлайн элементами могут быть небольшие промежутки размером с ширину пробельного символа, если в HTML между ними есть пробел или перенос строки. Их можно убрать стрёмным форматированием HTML кода, либо font-size: 0, либо просто использовать флексбоксы.
Сайтик, где можно генерить CSS фигуры https://bennettfeely.com/clippy для shape-outside, clip-path.
Сайтик с красивыми палитрами цветов https://lospec.com/palette-list
Сайтик с генератором цветов https://mycolor.space
Специфичность https://specifishity.com
nth-of-type / nth-child наглядные примеры http://nthmaster.com
Флоаты (очевидно, в контексте обтекания текстом / инлайн элементами, 2021 уже ведь).
Вместо clearfix есть более удобный display: flow-root, который заставляет родителя вмещать плавающие элементы (но что конкретно он делает, я не понял). На плавающий элемент можно повесить shape-outside, чтобы задать форму, по которой текст будет обтекать его, можно делать всякие странные вещи https://codepen.io/anonanon123/pen/jOLRZWE Чтобы сделать обтекание и слева, и справа, оба флоата в разметке должны идти перед обтекаемым элементом.
Позиционирование.
Static - дефолтное позиционирование в нормальном потоке. Relative - можно сдвинуть элемент относительно того, где он бы находился в нормальном потоке. Absolute - полностью убирает элемент из потока и позиционирует его относительно ближайшего не-static позиционированного предка. Fixed - относительно вьюпорта. Sticky - прилипает при скролле к вьюпорту (становится fixed), нужно обязательно указать какой-нибудь top/bottom/right/left. Кстати, центрировать position: absolute можно и не через трансформы, а margin: auto + inset: 0 (шортхенд для top/bottom/right/left).
Stacking context.
https://tiffanybbrown.com/2015/09/css-stacking-contexts-wtf
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index
Флексбоксы.
По поперечной оси элементы по умолчанию растягиваются (либо align-content/items/self). Распределение пространства для элементов по основной оси происходит в несколько этапов: сначала всем им назначается размер flex-basis (либо width / height, если он не задан, либо вроде max-content, если и они не заданы) минус бордеры, паддинги и марджины, то есть только контент. Потом делается перенос строк (если есть flex-wrap). Если после этого в строках не хватает места, то элементы ужимаются в соответствии с flex-shrink не сильнее, чем до min-content. При этом там такая формула, что степень ужатия зависит и от flex-shrink (чем больше, тем сильнее), и от размера элементов (большие элементы сжимаются сильнее, чем маленькие). А если есть свободное место, то оно распределяется просто с коэффициентами flex-grow. После этого всего применяются автоматические marginы и justify-content, если всё же свободное место осталось.
>размер flex-basis минус бордеры, паддинги и марджины, то есть только контент
Это объясняет, почему отличающиеся марджины, паддинги и бордеры ломают соотношения размеров флекс элементов. Что flex: 1 1 0 (то же самое, что flex: 1), что flex: 1 1 100% - не будут гарантировать одинаковых колонок в этом случае. Потому что во флексах при распределении размеров они просто выбрасываются из-за этого, что их всё равно нельзя сузить, например. Алсо большой min-content (длинные слова, например) могут ломать соотношения из-за того, что shrink ограничен min-contentом, но тут можно min-width: 0 выставить (и у тебя всё переполнится).
Видео про это https://youtu.be/fm3dSg4cxRI
https://codepen.io/anonanon123/pen/GRvLdWO
Вот пример, у него скопировал. Изначально выставил flex-basis на 1000px, но вычисления (пикрил девтулзы в Firefox) всё равно для 890px = 1000px - 5px - 5px (бордеры) - 50px - 50px (паддинги). И border-box не влияет на это поведение никак.
Это всё можно обойти, если обернуть каждый флекс-элемент, чтобы паддинги, марджины и бордеры входили в контент флекс-элемента, но гораздо проще использовать гриды, они подходят тут гораздо лучше.
order по умолчанию имеет значение 0.
flex-basis работает как универсальный размер вдоль главной оси.
flex-wrap: wrap-reverse просто меняет направление поперечной оси. Для управления направлениями обоих осей есть шортхенд flex-flow.
align-content влияет на распределение пространства между строками + их положение, тогда как align-items определяет положение элементов внутри строки, я так для себя это понимаю.
align-что-то - это про поперечную ось, justify-content - это про главную ось. В гридах похожие свойства, но там align-что-то - это всегда про вертикальную ось, а justify-что-то - всегда про горизонтальную. И почему-то неинтуитивно первой во всех сокращённых свойствах (по типу place-items) сначала указывается значение для вертикальной (align-что-то) оси.
Гриды.
Удобны, когда элементы выровнены по сетке друг относительно друга. Можно задать явно все строки и столбцы и назначить каждому элементу своё место в этой сетке, а можно использовать автоматически генерируемые строки и колонки.
У гридов очень много шортхендов, вот этот самый монструозный:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Grid_Template_Areas#grid-template
И ещё больше QoL фич, в частности неявное именование линий и областей, которыми, скорее всего, никто даже не пользуется:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Layout_using_Named_Grid_Lines
fr - fractional units - про распределение места.
Про auto:
>As a maximum represents the largest max-content size of the items in that track.
>As a minimum represents the largest minimum size of items in that track (specified by the min-width/min-height of the items). This is often, though not always, the min-content size.
>If used outside of minmax() notation, auto represents the range between the minimum and maxium described above. This behaves similarly to minmax(min-content,max-content) in most cases.
>Note: auto track sizes (and only auto track sizes) can be stretched by the align-content and justify-content properties. Therefore by default, an auto sized track will take up any remaining space in the grid container.
https://codepen.io/anonanon123/pen/abyxKvW
Про то, что auto = minmax(min-content, max-content) - это неправда, скорее auto = minmax(auto, auto). И он немного странно ведёт себя: в присутствии fr среди других размеров треков действительно похож на minmax(min-content, max-content). Но если есть только auto, то вроде как свободное именно от контента (не просто свободное место, как с fr) распределяется поровну между всеми auto грид-треками аналогично тому, что делает margin-left+right auto в флексбоксах. А сам margin auto в гридах выравнивает элемент только внутри грид клетки (эквивалентен place-self).
minmax - задаёт минимальный и максимальный размеры, но на самом деле умеет чуть больше. Самый частый паттерн использования - minmax(фикс. размер, 1fr), чтобы ограничить минимальный размер и растянуть по возможности. Очень часто юзается в сочетании с самым топовым правилом:
grid-template-columns: repeat(auto-fit, minmax(фикс. размер, 1fr));
repeat, кстати, работает и с повтором группы из нескольких строк / столбцов.
https://css-tricks.com/auto-sizing-columns-css-grid-auto-fill-vs-auto-fit
Различия auto-fit и auto-fill, второй бесполезный, как мне кажется.
Когда треков в гриде не хватает, генерируются автоматические, размер которых задаётся через grid-auto-columns/rows, а направление - через grid-auto-flow. Причём есть дополнительные значения row-dense и column-dense, которые нарушают порядок, но стараются как можно плотнее упаковать элементы.
Селекторы.
Чтобы выбрать n-ный элемент, использовать nth-of-type вместо nth-child, потому что nth-child выбирает элемент только, если он n-ый по счёту потомок среди всех потомков. Но с nth-of-type тоже нужно быть аккуратным, потому что если не указать тип элемента в селекторе: .child:nth-of-type(2), то выберутся вторые элементы с классом child для каждого типа элемента (для каждого HTML тега).
:nth-child(n+a):nth-child(-n+b) - интересный паттерн, чтобы выбрать потомков от a-ого по счёту, то b-ого.
:is позволяет меньше печатать и им можно делать что-то вроде декартова произведения селекторов, но его специфичность = максимально специфичному селектору внутри. Из-за этого будет сложнее переписать некоторые CSS правила, которые заданы через :is. :where - то же самое, что и :is, только не добавляет специфичность совсем. https://developer.mozilla.org/en-US/docs/Web/CSS/:where#examples Ещё статья в блоге гугла https://web.dev/css-is-and-where
Всякие странности CSS.
- box-sizing: border-box вместо дефолтного content-box - ставить по умолчанию всегда и везде, просто потому что, желательно вместе с margin: 0 и padding: 0. Всё же я не понимаю, как можно пользоваться этими дефолтными браузерными стилями. Хотя я слышал, что многим больше нравится normalize, а не reset всего.
- Горизонтальные внешние отступы схлопываются, но вертикальные - нет. Более того, вертикальные могут протечь из родителя, если у последнего нет бордера или паддинга.
- Между инлайн элементами могут быть небольшие промежутки размером с ширину пробельного символа, если в HTML между ними есть пробел или перенос строки. Их можно убрать стрёмным форматированием HTML кода, либо font-size: 0, либо просто использовать флексбоксы.
Сайтик, где можно генерить CSS фигуры https://bennettfeely.com/clippy для shape-outside, clip-path.
Сайтик с красивыми палитрами цветов https://lospec.com/palette-list
Сайтик с генератором цветов https://mycolor.space
Специфичность https://specifishity.com
nth-of-type / nth-child наглядные примеры http://nthmaster.com
Намного больше, уже пора в могилу вкатываться, а не вротенд.
Про фавиконки немного.
https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs
Минималистичный сетап для фавиконок в 2021. Но там нету про mask-icon - это для иконок закреплённых сайтов в сафари. Не знаю, может быть, так же, как browserconfig для винды - уже не нужно в 2021, либо просто опционально. Но SVG фавиконки сафари вроде до сих пор не поддерживает, ему нужно PNG 32x32.
https://www.leereamsnyder.com/blog/favicons-in-2021
Follow-up к посту по ссылке выше от другого рандома. В хроме до сих пор есть баг, из-за которого favicon.ico выбирается вместо SVG. Вроде решается, если добавить sizes="any" для favicon.ico...
https://css-tricks.com/dark-mode-favicons
Алсо можно делать SVG фавиконки под тёмную тему (вроде в режиме инкогнито в том числе оно триггерится).
https://realfavicongenerator.net
Такой сайтик нашёл, генерит всевозможные иконки, HTML код с <link>-ами, манифест (PWA, но у меня всё равно сервис воркеров нету, поэтому какая разница) и browserconfig для закреплённых сайтов в винде (который вроде уже не нужен).
Короче, просто favicon.ico в корень и не париться.
Да нет, просто выглядишь как подросток и энергии у тебя ещё хоть на что-то хватает.
Нормально вкатываться тут никто не умеет, Двач же, средний IQ 40.
Как раз наоборот, энергии почти нету. Была бы энергия, я бы больше за день успевал. Большую часть дня я бездельничаю. За сегодня, например, я всего лишь только про фавиконки почитал и повспоминал всякие вещи из CSS. То есть даже руками ничего не сделал, поэтому можно считать, что сделал +0% к прогрессу вката.
Я за этот месяц и год примерно столько же сделал.. И я тебя моложе.
>Горизонтальные внешние отступы схлопываются, но вертикальные - нет.
Не, ровно наоборот же. Ещё забыл про то, что во флексах и гридах это пофикшено и там не схлопываются.
https://stackoverflow.com/a/45087096
Способ впихнуть перенос строки в флексбокс без добавления лишней HTML разметки. Псевдоэлементы во флексах - это флекс-элементы. Можно задать для ::after flex-basis 100% и нулевую высоту, и поместить то, что хочешь перенести на следующую строку, после него через order: 1. Так можно впихнуть максимум два переноса строки.
Правда, проблема в том, что перенесённый элемент будет ниже на двойной gap, так что придётся добавить отрицательный margin сверху...
Не понимаю, почему не добавили нативную возможность триггерить перенос строки во флексах, приходится городить всякие странности. С другой стороны, почему тогда нельзя вынести из флекса элемент, который хочешь перенести, чтобы он просто блочным был под флексом? Наверное, можно, но всё равно кажется, что это могло бы быть неплохой фичей флексов.
Ещё не понимаю, как сделать, чтобы по первому клику проигрывать CSS анимацию в одну сторону, а по второму - в другую. Да, можно сделать две одинаковых анимации, у второй из которых кейфреймы в обратную сторону идут, но это довольно костыльно и не DRY.
Сделал в JS через web animations API (они как CSS анимации с кейфреймами, но которые можно создавать и запускать через JS): создаю анимацию, сразу же её ставлю на паузу, потом по клику делаю reverse + play. Так и не понял, как можно было чисто в CSS этого добиться (без костылей).
Кстати, вот ещё https://jsfiddle.net/fgxeu54t/28
Аболютно позиционированный элемент без top будет располагаться под позиционированными сиблингами, которые находятся перед ним в разметке. Я этого не знал, думал, что надо пердолиться с захардкоженным top для такого результата.
Неа. Я не знаю, что мне делать, и куда двигаться.
712x836, 0:09
CSS уже превратился в какую-то мешанину. Я пытаюсь использовать БЭМ, но это слабо помогает.
Нет, даже не трогал эту унылую духоту. По части фронтенда для меня на данный момент там нет ничего полезного, судя по списку тем в их курсах. Только с редаксом всё ещё не начал разбираться и не пробовал никакие CSS фреймворки.
Чёрт, этот parcel ещё большая срань, чем вебпак. Hot reloading работает кое-как даже для ванильного JS и периодически случается так, что вообще всё перестаёт обновляться. Я не знаю, наверное, что-то с кешем браузера или ещё что-то, но очень сильно бесит, когда ты что-то меняешь, видишь, что это не даёт результатов, и только через минут пять осознаёшь, что не ты виноват, а это ничего не обновилось.
И много времени потратил именно из-за того, что ни черта не обновлялось, а я думал, что это я виноват.
Я не могу, это бесполезно. Можно даже не пытаться. Зачем мне это всё.
Так-то всё это автомысли и их нужно лечить с помощью КПТ. Правда, я это говорю, но сам не умею почти. Ведь в тайне они так приятны, помогают мозгу расслабиться и уйти прокрастинировать...
Собственно, почитай о причинах прокрастинации:
https://ru.wikihow.com/прокрастинировать
Просто жить можно только на пенсию по шизе, увы. Можно ещё тексты писать, но не похоже, чтоб у тебя была к этому склонность.
Что я конкретно должен сейчас делать? У меня плохо получается вёрстка и почти нет в ней опыта, поэтому я её сейчас практикую. Уже прямо сейчас начинать ходить по собеседованиям что ли?
>>552437
Я не знаю, что такое автомысли и у меня нет интереса читать про это. Корень всех проблем не во мне, а в том, что меня пытаются заставить вкатываться в работу при том, что я бесполезен и никчёмен.
> Уже прямо сейчас начинать ходить по собеседованиям что ли?
Да. Ты плохо представляешь себе конкурентов и их знания верстки >>551821 < если это сделано с нуля без бутстрапов, то ты уже достаточно хорошо верстаешь, для поиска работы. Код я конечно не видел, но если у тебя размеры кнопок задаются паддингами, а не хардкодом длины и ширины - точно пора искать работу. А уж если ты знаешь про object-fit и при смене изображений в том, что ты сверстал, не едет вёрстка, то считай, что ты уже лучше большей части вкатанов которые мне попадались - возможно я просто на дне работаю, где худший человеческий капитал аккумулируется и почему-то ещё и я знаешь вёрстку.
Можешь просто пооткликаться на позиции, где тестовые высылают по вёрстке - увидишь, что это всегда что-то одноклеточное, в стиле формы обратной связи.
По js ты тоже уже изучил достаточно, я столько не знаю, хотя вроде второй год пишу на js всякий функционал.
> пытаются заставить вкатываться в работу при том, что я бесполезен и никчёмен
Почему бы не сходить ко врачу психотерапевту или неврологу за СИОЗС? Жить станет проще, я под СИОЗС вкатывался как раз, было очень хорошо, все проблемы просто рассосались от таблеток возможно после этого ты просто прекратишь вкатываться, тк не похоже, что ты прям хочешь этого - суть в том, что решения принимать проще будет, жить вообще станет проще под таблетками. Если есть проблемы, естественно. После прекращения курса не было отката назад.
Раскрывающиеся списки внизу анимированы через max-height, просто height почему-то не хочет анимироваться.
Скроллбар при открытии меню справа приходится убирать (делать overflow: hidden), потому что само меню позиционировано абсолютно, так что мимо него можно проскроллить вниз, если этого не сделать.
Обожаю гриды хотя бы из-за того, что этот компонент с ценами в звёздочках, можно сделать одним плоским гридом, и за счёт его расплющенности (а вот если бы существовал :has, то расплющенность не важна была бы...) можно сделать переключение вкладок без единой строки на JS. Для модальных окон с каруселями пришлось всё же JS написать, но оказалось не так плохо, несмотря на то, что это ваниль: я напихал атрибутов по типу data-opens-modal, data-closes-modal с айдишками всяких элементов, чтобы можно было в теории сколько угодно подобных модалок на страницу добавить, и сойдёт, короче.
Не знал, что нужно делать element.dispatchEvent(new Event('click', {bubbles: true})), чтобы затриггерить коллбэк, повешенный на событие. И если просто, например, сделать checkbox.checked = true, то событие не триггерится. И наоборот: само событие (change) не выставляет checked у чекбокса. Мне это нужно было, потому что каруселью по сути управляют только радиокнопки, а кнопки влево/вправо переключают радиокнопки, саму карусель не трогают.
Достал пердолинг с z-index, один из самых неприятных моментов в CSS (на равне или после стилизации скроллбаров). Сложно понять, что на странице находится на какой высоте и в каком stacking контексте. Box-shadow ещё иногда не работает, если не поставить position relative. Но хуже всего, что часто всё портится, когда меняешь на чём-нибудь z-index: после этого приходится для всего выше / ниже во всём stacking контексте тоже менять высоту. Возможно, есть смысл указывать z-index с интервалами в 10 единиц, как с номерами строк в бейсике, лол. Чтобы было пространство безопасно переместить элемент повыше/пониже или впихнуть между двумя существующими.
Раскрывающиеся списки внизу анимированы через max-height, просто height почему-то не хочет анимироваться.
Скроллбар при открытии меню справа приходится убирать (делать overflow: hidden), потому что само меню позиционировано абсолютно, так что мимо него можно проскроллить вниз, если этого не сделать.
Обожаю гриды хотя бы из-за того, что этот компонент с ценами в звёздочках, можно сделать одним плоским гридом, и за счёт его расплющенности (а вот если бы существовал :has, то расплющенность не важна была бы...) можно сделать переключение вкладок без единой строки на JS. Для модальных окон с каруселями пришлось всё же JS написать, но оказалось не так плохо, несмотря на то, что это ваниль: я напихал атрибутов по типу data-opens-modal, data-closes-modal с айдишками всяких элементов, чтобы можно было в теории сколько угодно подобных модалок на страницу добавить, и сойдёт, короче.
Не знал, что нужно делать element.dispatchEvent(new Event('click', {bubbles: true})), чтобы затриггерить коллбэк, повешенный на событие. И если просто, например, сделать checkbox.checked = true, то событие не триггерится. И наоборот: само событие (change) не выставляет checked у чекбокса. Мне это нужно было, потому что каруселью по сути управляют только радиокнопки, а кнопки влево/вправо переключают радиокнопки, саму карусель не трогают.
Достал пердолинг с z-index, один из самых неприятных моментов в CSS (на равне или после стилизации скроллбаров). Сложно понять, что на странице находится на какой высоте и в каком stacking контексте. Box-shadow ещё иногда не работает, если не поставить position relative. Но хуже всего, что часто всё портится, когда меняешь на чём-нибудь z-index: после этого приходится для всего выше / ниже во всём stacking контексте тоже менять высоту. Возможно, есть смысл указывать z-index с интервалами в 10 единиц, как с номерами строк в бейсике, лол. Чтобы было пространство безопасно переместить элемент повыше/пониже или впихнуть между двумя существующими.
Да как-то всё равно страшно пока что. Может быть, с начала декабря попробую начать. А скорее всего, никогда...
>СИОЗС
Не хочу есть всякие стрёмные таблетки, не хочу разговаривать со всякими психотерапевтами.
>>552618
Реакта должно же хватить для начала, в какую сторону расширять?
>>552956
Можно не жалеть, лучше высылайте раз в неделю немного денег и пустите жить в какой-нибудь подвал.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap/Basic_concepts
А, лол, я не знал, что так можно. Плюсом за бесплатно нативная навигация свайпами. И даже поддержка браузеров неплохая. Навигация по секциям через a[href=#section-id]. Но в этом случае придётся пердолиться с тем, чтобы подсветить выбранную секцию в навигации. Видимо, слушать скролл ивенты, ждать, когда юзер перестаёт скроллить, и находить ближайший к положению скролла элемент.
https://github.com/w3c/csswg-drafts/issues/156
Вот что-то подобное было бы неплохо. Чтобы просто было событие snapchange, в котором таргет - то, на какой элемент скролл снапнулся.
Посмотрел немного про реакт. Не знал про defaultProps и prop-types (потому что нинужно). Для последнего есть бабель плагин, который выпиливает все проверки типов (чтобы выключить их в продакшене), чтобы в рантайме бессмысленного оверхеда не было, норм.
https://reactjs.org/docs/higher-order-components.html
Увидел интересный паттерн с HOC, чтобы добавлять дополнительные функциональность и состояние компонентам: HOC оборачивает существующий компонент, реализует всякое и передаёт все нужные ручки и данные через пропсы оригинальному компоненту. Как я понял, так делали раньше то, что сейчас можно проще и читабельнее реализовать на хуках.
Чтобы навешивать сразу несколько обёрток на компонент, удобно сделать функцию withSomething не просто HOC, а функцией, которая берёт какие-то опции и возвращает HOC. Чтобы проще было делать композицию из этих обёрток:
compose(withSomething(), withSomethingElse(options))(WrappedComponent)
Алсо я не знал, что spread синтаксис работает и внутри деструктуризации объекта:
const { propA, propB, ...otherProps } = props;
Можно так оторвать от объекта несколько кусочков. Как раз полезно в контексте этого паттерна с HOC, чтобы не передавать в обёртываемый комопнент лишние пропсы, которые добавляет компонент-обёртка. С деструктуризацией массивов то же самое есть.
Чем HOC лучше более очевидных и читаемых рендер пропсов? Я думаю, если просто хочешь сделать обёртку и не передавать дочерним компонентам ничего нового из обёртки, то лучше и проще делать через рендер пропс. В остальных случаях не знаю, сложно сказать. Наверное, стоит использовать только, если собираешься чейнить несколько HOC-ов, тогда рендер пропсы вложенные в рендер пропсы будут выглядеть хуже, хоть и незначительно, если честно.
С третьей стороны, а вообще нужны ли HOC, если есть useContext? Зачем передавать пропсы, если можно этого просто не делать? Вот вроде как раз в редаксе раньше использовались HOC (connect), но потом поменяли на context provider, и это выглядит в разы проще. Ещё не смотрел про редакс подробно, но походу сейчас почти нет разницы между ним и хуками useContext+useReducer.
С четвёртой стороны, можно вообще хранить состояние внутри компонента и обходиться useState.
https://reactjs.org/docs/refs-and-the-dom.html
Не знал, что ref можно цеплять на кастомные классовые компоненты. Мне казалось, что это только, чтобы получить ссылку на DOM-элемент или в случае с функциональными компонентами - сохранить какое-то значение между рендерами.
https://reactjs.org/docs/forwarding-refs.html
И про forwardRef тоже не знал. Но обе эти фичи, наверное, плохо пахнут. Особенно вторая, потому что нарушает инкапсуляцию компонента. Ну вторая ещё может использоваться, чтобы пробросить вниз ref через обёртки в случае с тем HOC паттерном, чтобы был ref на оригинальный компонент, а не обёртку. Тут приходится так делать, как ни крути.
И всё равно не понимаю, зачем может понадобиться ref на кастомный классовый компонент. Почему не просто инкапсулировать эту логику внутри компонента, чтобы она триггерилась в зависимости от значений пропсов. Вместо того, чтобы императивно вызывать метод компонента-потомка из родительского. Плюс это всё не будет работать с функциональными компонентами, потому что они не инстанциируются.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap/Basic_concepts
А, лол, я не знал, что так можно. Плюсом за бесплатно нативная навигация свайпами. И даже поддержка браузеров неплохая. Навигация по секциям через a[href=#section-id]. Но в этом случае придётся пердолиться с тем, чтобы подсветить выбранную секцию в навигации. Видимо, слушать скролл ивенты, ждать, когда юзер перестаёт скроллить, и находить ближайший к положению скролла элемент.
https://github.com/w3c/csswg-drafts/issues/156
Вот что-то подобное было бы неплохо. Чтобы просто было событие snapchange, в котором таргет - то, на какой элемент скролл снапнулся.
Посмотрел немного про реакт. Не знал про defaultProps и prop-types (потому что нинужно). Для последнего есть бабель плагин, который выпиливает все проверки типов (чтобы выключить их в продакшене), чтобы в рантайме бессмысленного оверхеда не было, норм.
https://reactjs.org/docs/higher-order-components.html
Увидел интересный паттерн с HOC, чтобы добавлять дополнительные функциональность и состояние компонентам: HOC оборачивает существующий компонент, реализует всякое и передаёт все нужные ручки и данные через пропсы оригинальному компоненту. Как я понял, так делали раньше то, что сейчас можно проще и читабельнее реализовать на хуках.
Чтобы навешивать сразу несколько обёрток на компонент, удобно сделать функцию withSomething не просто HOC, а функцией, которая берёт какие-то опции и возвращает HOC. Чтобы проще было делать композицию из этих обёрток:
compose(withSomething(), withSomethingElse(options))(WrappedComponent)
Алсо я не знал, что spread синтаксис работает и внутри деструктуризации объекта:
const { propA, propB, ...otherProps } = props;
Можно так оторвать от объекта несколько кусочков. Как раз полезно в контексте этого паттерна с HOC, чтобы не передавать в обёртываемый комопнент лишние пропсы, которые добавляет компонент-обёртка. С деструктуризацией массивов то же самое есть.
Чем HOC лучше более очевидных и читаемых рендер пропсов? Я думаю, если просто хочешь сделать обёртку и не передавать дочерним компонентам ничего нового из обёртки, то лучше и проще делать через рендер пропс. В остальных случаях не знаю, сложно сказать. Наверное, стоит использовать только, если собираешься чейнить несколько HOC-ов, тогда рендер пропсы вложенные в рендер пропсы будут выглядеть хуже, хоть и незначительно, если честно.
С третьей стороны, а вообще нужны ли HOC, если есть useContext? Зачем передавать пропсы, если можно этого просто не делать? Вот вроде как раз в редаксе раньше использовались HOC (connect), но потом поменяли на context provider, и это выглядит в разы проще. Ещё не смотрел про редакс подробно, но походу сейчас почти нет разницы между ним и хуками useContext+useReducer.
С четвёртой стороны, можно вообще хранить состояние внутри компонента и обходиться useState.
https://reactjs.org/docs/refs-and-the-dom.html
Не знал, что ref можно цеплять на кастомные классовые компоненты. Мне казалось, что это только, чтобы получить ссылку на DOM-элемент или в случае с функциональными компонентами - сохранить какое-то значение между рендерами.
https://reactjs.org/docs/forwarding-refs.html
И про forwardRef тоже не знал. Но обе эти фичи, наверное, плохо пахнут. Особенно вторая, потому что нарушает инкапсуляцию компонента. Ну вторая ещё может использоваться, чтобы пробросить вниз ref через обёртки в случае с тем HOC паттерном, чтобы был ref на оригинальный компонент, а не обёртку. Тут приходится так делать, как ни крути.
И всё равно не понимаю, зачем может понадобиться ref на кастомный классовый компонент. Почему не просто инкапсулировать эту логику внутри компонента, чтобы она триггерилась в зависимости от значений пропсов. Вместо того, чтобы императивно вызывать метод компонента-потомка из родительского. Плюс это всё не будет работать с функциональными компонентами, потому что они не инстанциируются.
Посмотрел про то, как подключать шрифты локально (@font-face), вроде нужны в основном WOFF и WOFF2. Там ещё есть какой-то древний формат для IE (EOT) и все туториалы его упоминают, но аж IE9+ поддерживает WOFF, так что не нужно. Вообще WOFF2 достаточно уже, IE11 уже недолго осталось жить вроде.
Только сейчас узнал, про это в свойстве background:
>The <bg-size> value may only be included immediately after <position>, separated with the '/' character, like this: "center/80%".
У меня очень часто из-за этого не работало ничего, не знал про эту особенность, я забивал на это и просто расписывал отдельно background-image/position/size и прочее.
Немного про градиенты посмотрел. Не знал про linear/radial-repeating-gradient, им можно всякие полосочки рисовать https://codepen.io/anonanon123/full/eYGOLQj
https://codepen.io/anonanon123/full/LYzPgPP
Я пытался сделать shimmer эффект на кнопке, но я не понимаю, в чём проблема: то ли цвета не такие, то ли ещё что-то, но что бы я ни делал, он выглядит как полное дерьмо. Ещё и, оказывается, в анимации нельзя нормально указать задержку между повторениями. И для background-position почему-то не работают значения в процентах, пришлось рисовать градиент на очень большом фоне.
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
Короче, srcset + sizes для <img> - если хочешь, чтобы картинки загружались в зависимости от размера вьюпорта или плотности пикселей. srcset - просто перечисляет список доступных картинок. Если картинки разного размера (на странице), то рядом с именем картинки указывается её (intrinsic) ширина в пикселях как %Ширина%w. sizes - тут описание того, когда использовать картинку какого размера в зависимости от медиа-запроса: "(max-width: 1000px) 400px" - выберет из srcset картинку размером 400px, если ширина вьюпорта меньше 1000px. Если картинки одинакового размера (на странице, например, какие-нибудь иконки), можно вместо размера указывать плотность пикселей, например 1.5x, 2x, 3x.
Необязательно делать медиа-запрос на размер вьюпорта, можно, например, выдавать разные картинки в зависимости от prefers-reduced-motion (выдать статичную картинку вместо гифки, например), prefers-color-scheme или prefers-contrast. Хотя сейчас гифки вряд ли используют, наверное, всё делают спрайтовыми анимациями (background-position). Там ещё есть медиа-запросы на ориентацию экрана (на телефоне).
Ещё есть <picture> и я не понимаю, чем он отличается от <img> с srcset+sizes, вроде как то же самое же умеет делать.
https://blog.bitsrc.io/why-you-should-use-picture-tag-instead-of-img-tag-b9841e86bf8b
Вроде как лучше использовать picture, чтобы выбирать между картинками по любой другой причине, кроме как размер вьюпорта.
Не знал, что у картинок есть loading="lazy/eager", думал, что их ленивая подгрузка только через intersection observer делается. Про него тоже посмотрел, там всё просто: он изначально триггерит колбэк для каждого добавленного элемента и после вызывает его каждый раз, когда он пропадает / появляется во вьюпорте. Опцией rootMargin можно изменить размер прямоугольника, с которым пересекаются элементы (увеличить, чтобы пересечение срабатывало заранее или уменьшить, чтобы срабатывало только, когда элемент влез внутрь вьюпорта на какое-то расстояние).
Потыкал ещё немного в реакт, конкретно в контекст. Там, оказывается, его можно и без хуков использовать, через рендер пропс у Context.Consumer, но хуки очевидно удобнее.
Посмотрел про то, как подключать шрифты локально (@font-face), вроде нужны в основном WOFF и WOFF2. Там ещё есть какой-то древний формат для IE (EOT) и все туториалы его упоминают, но аж IE9+ поддерживает WOFF, так что не нужно. Вообще WOFF2 достаточно уже, IE11 уже недолго осталось жить вроде.
Только сейчас узнал, про это в свойстве background:
>The <bg-size> value may only be included immediately after <position>, separated with the '/' character, like this: "center/80%".
У меня очень часто из-за этого не работало ничего, не знал про эту особенность, я забивал на это и просто расписывал отдельно background-image/position/size и прочее.
Немного про градиенты посмотрел. Не знал про linear/radial-repeating-gradient, им можно всякие полосочки рисовать https://codepen.io/anonanon123/full/eYGOLQj
https://codepen.io/anonanon123/full/LYzPgPP
Я пытался сделать shimmer эффект на кнопке, но я не понимаю, в чём проблема: то ли цвета не такие, то ли ещё что-то, но что бы я ни делал, он выглядит как полное дерьмо. Ещё и, оказывается, в анимации нельзя нормально указать задержку между повторениями. И для background-position почему-то не работают значения в процентах, пришлось рисовать градиент на очень большом фоне.
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
Короче, srcset + sizes для <img> - если хочешь, чтобы картинки загружались в зависимости от размера вьюпорта или плотности пикселей. srcset - просто перечисляет список доступных картинок. Если картинки разного размера (на странице), то рядом с именем картинки указывается её (intrinsic) ширина в пикселях как %Ширина%w. sizes - тут описание того, когда использовать картинку какого размера в зависимости от медиа-запроса: "(max-width: 1000px) 400px" - выберет из srcset картинку размером 400px, если ширина вьюпорта меньше 1000px. Если картинки одинакового размера (на странице, например, какие-нибудь иконки), можно вместо размера указывать плотность пикселей, например 1.5x, 2x, 3x.
Необязательно делать медиа-запрос на размер вьюпорта, можно, например, выдавать разные картинки в зависимости от prefers-reduced-motion (выдать статичную картинку вместо гифки, например), prefers-color-scheme или prefers-contrast. Хотя сейчас гифки вряд ли используют, наверное, всё делают спрайтовыми анимациями (background-position). Там ещё есть медиа-запросы на ориентацию экрана (на телефоне).
Ещё есть <picture> и я не понимаю, чем он отличается от <img> с srcset+sizes, вроде как то же самое же умеет делать.
https://blog.bitsrc.io/why-you-should-use-picture-tag-instead-of-img-tag-b9841e86bf8b
Вроде как лучше использовать picture, чтобы выбирать между картинками по любой другой причине, кроме как размер вьюпорта.
Не знал, что у картинок есть loading="lazy/eager", думал, что их ленивая подгрузка только через intersection observer делается. Про него тоже посмотрел, там всё просто: он изначально триггерит колбэк для каждого добавленного элемента и после вызывает его каждый раз, когда он пропадает / появляется во вьюпорте. Опцией rootMargin можно изменить размер прямоугольника, с которым пересекаются элементы (увеличить, чтобы пересечение срабатывало заранее или уменьшить, чтобы срабатывало только, когда элемент влез внутрь вьюпорта на какое-то расстояние).
Потыкал ещё немного в реакт, конкретно в контекст. Там, оказывается, его можно и без хуков использовать, через рендер пропс у Context.Consumer, но хуки очевидно удобнее.
Я вообще ничего не сделал за сегодня толкового. А надо было доделать вёрстку той странички и доделать поиск фильмов наконец-то. Я вряд ли уже куда-либо вкачусь, короче. Мне так всё это надоело, почему я должен заниматься всем этим.
- box-shadow - только про прямоугольники, а drop-shadow может, например, сделать тень у SVG или у элемента с clip-path или у треугольника, сделанного через border
- drop-shadow не умеет в inset тень и у неё нету параметра spread-радиуса, то есть размер строго равен размеру фигуры
https://medium.com/masmovil-engineering/layers-layers-layers-be-careful-6838d59c07fa
https://rashidovr.medium.com/reflow-repaint-composite-что-это-и-как-это-работает-a777c5760295
Ещё отличие в том, что элементы с filter вроде как триггерят создание отдельных слоёв, благодаря чему делается repaint не всей страницы только ради того, чтобы отрендерить изменения свойства filter, а только репэинт слоя элемента с filter. С box-shadow, как я понимаю, этого по умолчанию не происходит. И вот, чтобы специально затриггерить вынос элемента в отдельный слой, когда-то давно использовали хак transform: translateZ(0), сейчас есть ещё will-change: <название анимации>. Но вроде этим не стоит злоупотреблять, потому что premature optimization.
https://codepen.io/leolucas/pen/PoPXrrY
И вот вроде тогда достаточно прописать will-change: box-shadow, чтобы не происходил repaint всей страницы? На самом деле, можно ещё лучше: вообще никакие тени не анимировать, а сделать псевдоэлемент с тенью под элементом и анимировать у него transform и opacity. Тогда вообще repaint-ов не будет.
В общем, вроде с самими box-shadow ничего плохого нет, просто они относительно дорогие сами по себе, как и градиенты, например, и по умолчанию триггерят репэинт всей страницы, но этого можно избежать.
В первой статье есть пример с анимацией свойства left, чтобы двигать позиционированный блок. По дефолту это триггерит очень много repaint-ов, но если прописать will-change: left, то у меня вроде repaint-ов вообще вроде не происходит, только композиция слоёв.
Репэинты, например, триггерят изменения цветов, фонов и подобное. Плюс репэинты происходят после reflow обычно. То есть моя говнокнопка с говно-shimmer эффектом из-за анимации background-position постоянно триггерит repaint. На самом деле, не постоянно и всё не так плохо: браузер достаточно умён, чтобы делать repaint только, когда по кнопке реально визуально пробегает отблеск, несмотря на то, что background-position анимируется постоянно бесконечно.
Если честно, не уверен во всём этом, возможно, я не прав в каждом слове... Но мне уже всё равно.
https://css-tricks.com/holy-albatross-with-widths
Хак с флексбоксом, которым можно без медиа-запросов менять "направление" флекс-элементов с горизонтального на вертикальное. Это лучше медиа-запросов, потому что элементы подстраиваются не под ширину экрана, а под ширину родительского контейнера, в общем, container queries на очень минималках (для одного конкретного вырожденного случая).
Основная суть в этом правиле, которое применяется для каждого флекс-элемента:
min-width: clamp(0, (var(--breakpoint) - 100%) x 999, 100%);
Если breakpoint больше ширины родителя (100%), то разность величины брейкпоинта и 100% вернёт что-то положительное, это число домножится на какое-то большое (999) значение, поэтому clamp возвращает 100%, из-за чего элементы располагаются по одному на каждую строку. Если breakpoint < ширины родителя, то разность отрицательная, min-width становится 0 и всё выравнивается в одну строку.
Мне сложно понять, зачем это, потому что почему не просто flex-wrap, ну да ладно.
https://css-tricks.com/building-progress-ring-quickly
Интересный способ сделать круговой прогресс-бар. Там используется SVG хак stroke-dasharray и stroke-dashoffset, чтобы сделать одну длинную чёрточку длинною с длину окружности (и после неё пустой промежуток такой же длины) и задвинуть её из области видимости.
https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/conic-gradient()
Альтернативно можно использовать конические градиенты для этого, не знал про них. Ими же можно легко делать пай-чарты. Но вариант с SVG может быть красивее, там можно сделать stroke-linecap закруглённый, с градиентом не выйдет так.
- box-shadow - только про прямоугольники, а drop-shadow может, например, сделать тень у SVG или у элемента с clip-path или у треугольника, сделанного через border
- drop-shadow не умеет в inset тень и у неё нету параметра spread-радиуса, то есть размер строго равен размеру фигуры
https://medium.com/masmovil-engineering/layers-layers-layers-be-careful-6838d59c07fa
https://rashidovr.medium.com/reflow-repaint-composite-что-это-и-как-это-работает-a777c5760295
Ещё отличие в том, что элементы с filter вроде как триггерят создание отдельных слоёв, благодаря чему делается repaint не всей страницы только ради того, чтобы отрендерить изменения свойства filter, а только репэинт слоя элемента с filter. С box-shadow, как я понимаю, этого по умолчанию не происходит. И вот, чтобы специально затриггерить вынос элемента в отдельный слой, когда-то давно использовали хак transform: translateZ(0), сейчас есть ещё will-change: <название анимации>. Но вроде этим не стоит злоупотреблять, потому что premature optimization.
https://codepen.io/leolucas/pen/PoPXrrY
И вот вроде тогда достаточно прописать will-change: box-shadow, чтобы не происходил repaint всей страницы? На самом деле, можно ещё лучше: вообще никакие тени не анимировать, а сделать псевдоэлемент с тенью под элементом и анимировать у него transform и opacity. Тогда вообще repaint-ов не будет.
В общем, вроде с самими box-shadow ничего плохого нет, просто они относительно дорогие сами по себе, как и градиенты, например, и по умолчанию триггерят репэинт всей страницы, но этого можно избежать.
В первой статье есть пример с анимацией свойства left, чтобы двигать позиционированный блок. По дефолту это триггерит очень много repaint-ов, но если прописать will-change: left, то у меня вроде repaint-ов вообще вроде не происходит, только композиция слоёв.
Репэинты, например, триггерят изменения цветов, фонов и подобное. Плюс репэинты происходят после reflow обычно. То есть моя говнокнопка с говно-shimmer эффектом из-за анимации background-position постоянно триггерит repaint. На самом деле, не постоянно и всё не так плохо: браузер достаточно умён, чтобы делать repaint только, когда по кнопке реально визуально пробегает отблеск, несмотря на то, что background-position анимируется постоянно бесконечно.
Если честно, не уверен во всём этом, возможно, я не прав в каждом слове... Но мне уже всё равно.
https://css-tricks.com/holy-albatross-with-widths
Хак с флексбоксом, которым можно без медиа-запросов менять "направление" флекс-элементов с горизонтального на вертикальное. Это лучше медиа-запросов, потому что элементы подстраиваются не под ширину экрана, а под ширину родительского контейнера, в общем, container queries на очень минималках (для одного конкретного вырожденного случая).
Основная суть в этом правиле, которое применяется для каждого флекс-элемента:
min-width: clamp(0, (var(--breakpoint) - 100%) x 999, 100%);
Если breakpoint больше ширины родителя (100%), то разность величины брейкпоинта и 100% вернёт что-то положительное, это число домножится на какое-то большое (999) значение, поэтому clamp возвращает 100%, из-за чего элементы располагаются по одному на каждую строку. Если breakpoint < ширины родителя, то разность отрицательная, min-width становится 0 и всё выравнивается в одну строку.
Мне сложно понять, зачем это, потому что почему не просто flex-wrap, ну да ладно.
https://css-tricks.com/building-progress-ring-quickly
Интересный способ сделать круговой прогресс-бар. Там используется SVG хак stroke-dasharray и stroke-dashoffset, чтобы сделать одну длинную чёрточку длинною с длину окружности (и после неё пустой промежуток такой же длины) и задвинуть её из области видимости.
https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/conic-gradient()
Альтернативно можно использовать конические градиенты для этого, не знал про них. Ими же можно легко делать пай-чарты. Но вариант с SVG может быть красивее, там можно сделать stroke-linecap закруглённый, с градиентом не выйдет так.
Небольшой рефрешер на HTML.
Нужно сразу упомянуть, что я понимаю, что фап на семантичную разметку - это всё один большой прикол и на практике вряд ли кто-то этим занимается, кроме реально крупных сайтов. И на семантику и a11y наплевать даже даже тем, кто непосредственно на неё фапает или делает вид https://youtu.be/yXW2uvA-SsY
Мне просто надо было уяснить для себя несколько вещей.
https://css-tricks.com/how-to-section-your-html
Необоснованно длинная и душная статья про HTML5 секционные теги, читал по диагонали.
В общем, <main> - основной контент на странице. Он сам по себе не является sectioning контентом (это то, что создаёт секцию в аутлайне документа и может иметь <header> и <footer>), то есть внутри могут быть только всякие <section>, <article> и прочее, и они внутри себя уже создают секции.
Типикал страница состоит из:
- <nav> - основная навигация по сайту (или по длинной статье, например, хотя вроде не советуют для всего подряд использовать его, потому что каждый <nav> добавляет новый лэндмарк), обычно что-то, что повторяется на каждой странице сайта или для каждого артикла, часто содержит в себе список ссылок, но необязательно именно список.
- <header> - в случае с сайтом обычно содержит логотип и навигацию, <footer> - какая-то менее важная навигация, неважная информация. Оба внутри себя могут содержать sectioning content, но без <header> или <footer> на любом уровне вложенности.
- <article> - какая-то самостоятельная контентная единица (комментарий, пост, что-то, что могло бы быть блоком по БЭМу), <section> - раздел какого-то текста, например, несамостоятельная единица (по аналогии - элемент по БЭМу). В обоих можно использовать header и footer, например, можно сверху в header добавить какую-то информацию об авторе, навигацию по статье, а в конец - список тегов.
- <aside> - что-то тангенциальное основному контенту, необязательно буквально боковая панель, например, внутри <article> может представлять какую-то дополнительную сопровождающую информацию между делом
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories классификация sectioning, flow, sectioning, heading, phrasing content - это всё просто термины из спеки HTML. В частности можно по ним и спеке определить, какие элементы в какие можно вкладывать.
Sectioning content очень желательно помечать заголовками. И тег заголовка лучше ставить в начале, и вообще располагать теги в порядке прочтения контента. Если что, можно поменять порядок флексбоксом или гридом.
Лучше использовать сквозную иерархию заголовков (скрывать ненужные через .visually-hidden), внутри одной секции не иметь несколько заголовков одного уровня. По спеке можно было бы везде использовать <h1>, чтобы браузер сам определил по вложенности уровни заголовков и построил аутлайн, но это не реализовано ни в одном браузере. Поэтому нужно сквозную иерархию делать.
https://youtu.be/NexL5_Vdoq8
Видео про это.
https://weblind.ru
https://www.accessibility-developer-guide.com
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA
Все эти роли и ариа-булшит - это всё настолько запутанно, что лучше туда даже не лезть, слишком глубокая кроличья нора. Нужно реально понимать, что ты делаешь. Страница старбакса, которую я копировал, использует всякие сложные роли по типу tablist, реализует как-то по-умному карусели, но, короче, во-первых, было бы странно, если бы у них не был идеальный сайт, а во-вторых, это всё не нужно, я так думаю.
Я думаю, достаточно этого:
1. Используешь по возможности семантичные теги (будут по крайней мере хорошие лэндмарки и местами нормальный UX, например, нативный select vs велосипед - последний никогда не будет лучше), прописываешь заголовки (будет хороший аутлайн) и label-ы для элементов форм (плюс по необходимости fieldset+legend).
2. Скрываешь визуальный мусор (декоративные картинки, например) через aria-hidden="true", но стараешься не скрывать ничего из контента. Исключение - всякие всплывающие виджеты, с которых вручную снимаешь скрытие. И их тут лучше скрывать через visibility hidden - то есть одновременно и от скринридеров, и от людей. У таких всплывающих элементов (бургерное меню, модальное окно) делаешь tabindex="-1", изначально фокусируешься на них при появлении и трапуешь фокус внутри например этим https://www.npmjs.com/package/focus-trap
3. Скрываешь избыточную для зрячего информацию (подписи к кнопкам с визуальными иконками, например) через .visually-hiiden. Альтернативно можно ещё использовать aria-label и aria-labeledby.
4. Добавляешь ещё больше визуально скрытой избыточной информации:
- Есть кнопка с иконкой? Впихни внутрь скрытый текст с описанием того, что она делает.
- Есть всплывающая на hover подсказка? Впихни текст подсказки прямо скрытым текстом рядом с элементом, саму всплывающую подсказку сделай aria-hidden. Карусель / список вкладок? просто вываливаешь весь контент разом, не пытаешься реализовать их. Вот это всё - чисто визуальные элементы, я уверен, они плохо воспринимаются, если не видишь их глазами.
- Кнопка-переключатель? Используй чекбокс и забей. Ну ладно, тут можно альтернативно заюзать aria-pressed. Но вообще, если нужен какой-то нестандартный элемент или нужно полностью заменить стандартный, то самое простое - повесить aria-hidden на свой велосипед и с клавиатуры сделать доступным нормальный HTML элемент (как я делал выше с кастомным селектом). Выше кидал статью про такой способ.
Например, пускай хочется сделать input[type=range] с двумя кружочками, чтобы выбирать промежуток между двумя значениями. Может быть полезно для фильтра по ценам, например. С клавиатуры и для скринридеров можно просто показать два обычных инпута с одним кружочком, которые будут синхронизированы с кастомным инпутом, и всё.
Тогда в теории тебе вообще никакие aria атрибуты, кроме aria-hidden, не понадобятся. И это должно выглядеть не так уж и плохо. А пердолинг с ролями, другими ариа-атрибутами скорее сделает всё только хуже, если что-то неправильно реализуешь.
https://developer.mozilla.org/en-US/docs/Web/HTML/Microdata
Способ аннотировать свой HTML какой-то дополнительной семантикой. Вроде как это относится к базовой SEO оптимизации. Берётся какая-то схема пример http://schema.org/SoftwareApplication вешается на какой-то элемент через itemscope+itemtype, на вложенные элементы вешается itemprop (причём они сами могут быть какими-то составными значениями).
Ещё есть метатеги всякие: author, keywords и description - самые основные. Но ещё есть вот такое:
https://ogp.me
Ещё дополнительная мета-информация о сайте. Может использоваться, например, когда вставляешь ссылку на сайт в какой-то соцсети, и она отображается как карточка, контент для которой берётся как раз из этих мета-тегов. Кто-то добавляет свои мета-теги для этих же целей:
https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
В HTML, помимо секционных элементов, есть ещё очень много всяких других семантичных тегов. Не все одинаково полезны, но вот достойные упоминания:
- <figure>+<figcaption> - какая-то иллюстрация, возможно, небольшой отрывок текста или цитата, с подписью.
- Семантичные теги для таблиц вроде <caption>, <thead> (полностью оборачивает шапку в отличие от <th>), <tbody>, <tfoot> (тут может быть summary, например). Пример таблицы, свёрстанной с ними: https://github.com/mdn/learning-area/blob/main/css/styling-boxes/styling-tables/punk-bands-complete.html
- <dl>, <dt>, <dd> - работают как отображение из одних значений (<dt>) в другие (<dd>). Подходят там, где таблица избыточна (таблицы отображают пару каких-то значений в одно, но иногда нужно описать соответствие между просто парами значений). Например, характеристики какого-нибудь товара в магазине.
- <em> vs <i>, <strong> vs <b> - первые обладают семантикой, вторые - только для выделения текста.
- <time> для временной отметки. Если внутри человеческое обозначение какого-то момента времени (например, "вчера"), то дополнительно использовать атрибут datetime.
- <address> для контактной информации. И тут стоит ещё вспомнить, что в href можно писать значения "..." и "tel:...". С телефона второй, например, сразу откроет приложение телефона и введёт номер. Алсо можно по-разному их стилизовать через селектор a[href^=""], например, добавить иконку какую-нибудь. Для ввода самих этих значений можно использовать input[type=tel] и input[tyle=email] - у них есть валидация по умолчанию и с телефона открывается клавиатура специальная. Можно, кстати, переопределить валидацию по умолчанию через атрибут pattern, там просто регулярка указывается.
- <q>, <blockquote> и <cite> для цитат
- <fieldset>+<legend>
- <progress> и <meter> (последний менее полезен)
- <datalist>
- <optgroup>
Небольшой рефрешер на HTML.
Нужно сразу упомянуть, что я понимаю, что фап на семантичную разметку - это всё один большой прикол и на практике вряд ли кто-то этим занимается, кроме реально крупных сайтов. И на семантику и a11y наплевать даже даже тем, кто непосредственно на неё фапает или делает вид https://youtu.be/yXW2uvA-SsY
Мне просто надо было уяснить для себя несколько вещей.
https://css-tricks.com/how-to-section-your-html
Необоснованно длинная и душная статья про HTML5 секционные теги, читал по диагонали.
В общем, <main> - основной контент на странице. Он сам по себе не является sectioning контентом (это то, что создаёт секцию в аутлайне документа и может иметь <header> и <footer>), то есть внутри могут быть только всякие <section>, <article> и прочее, и они внутри себя уже создают секции.
Типикал страница состоит из:
- <nav> - основная навигация по сайту (или по длинной статье, например, хотя вроде не советуют для всего подряд использовать его, потому что каждый <nav> добавляет новый лэндмарк), обычно что-то, что повторяется на каждой странице сайта или для каждого артикла, часто содержит в себе список ссылок, но необязательно именно список.
- <header> - в случае с сайтом обычно содержит логотип и навигацию, <footer> - какая-то менее важная навигация, неважная информация. Оба внутри себя могут содержать sectioning content, но без <header> или <footer> на любом уровне вложенности.
- <article> - какая-то самостоятельная контентная единица (комментарий, пост, что-то, что могло бы быть блоком по БЭМу), <section> - раздел какого-то текста, например, несамостоятельная единица (по аналогии - элемент по БЭМу). В обоих можно использовать header и footer, например, можно сверху в header добавить какую-то информацию об авторе, навигацию по статье, а в конец - список тегов.
- <aside> - что-то тангенциальное основному контенту, необязательно буквально боковая панель, например, внутри <article> может представлять какую-то дополнительную сопровождающую информацию между делом
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories классификация sectioning, flow, sectioning, heading, phrasing content - это всё просто термины из спеки HTML. В частности можно по ним и спеке определить, какие элементы в какие можно вкладывать.
Sectioning content очень желательно помечать заголовками. И тег заголовка лучше ставить в начале, и вообще располагать теги в порядке прочтения контента. Если что, можно поменять порядок флексбоксом или гридом.
Лучше использовать сквозную иерархию заголовков (скрывать ненужные через .visually-hidden), внутри одной секции не иметь несколько заголовков одного уровня. По спеке можно было бы везде использовать <h1>, чтобы браузер сам определил по вложенности уровни заголовков и построил аутлайн, но это не реализовано ни в одном браузере. Поэтому нужно сквозную иерархию делать.
https://youtu.be/NexL5_Vdoq8
Видео про это.
https://weblind.ru
https://www.accessibility-developer-guide.com
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA
Все эти роли и ариа-булшит - это всё настолько запутанно, что лучше туда даже не лезть, слишком глубокая кроличья нора. Нужно реально понимать, что ты делаешь. Страница старбакса, которую я копировал, использует всякие сложные роли по типу tablist, реализует как-то по-умному карусели, но, короче, во-первых, было бы странно, если бы у них не был идеальный сайт, а во-вторых, это всё не нужно, я так думаю.
Я думаю, достаточно этого:
1. Используешь по возможности семантичные теги (будут по крайней мере хорошие лэндмарки и местами нормальный UX, например, нативный select vs велосипед - последний никогда не будет лучше), прописываешь заголовки (будет хороший аутлайн) и label-ы для элементов форм (плюс по необходимости fieldset+legend).
2. Скрываешь визуальный мусор (декоративные картинки, например) через aria-hidden="true", но стараешься не скрывать ничего из контента. Исключение - всякие всплывающие виджеты, с которых вручную снимаешь скрытие. И их тут лучше скрывать через visibility hidden - то есть одновременно и от скринридеров, и от людей. У таких всплывающих элементов (бургерное меню, модальное окно) делаешь tabindex="-1", изначально фокусируешься на них при появлении и трапуешь фокус внутри например этим https://www.npmjs.com/package/focus-trap
3. Скрываешь избыточную для зрячего информацию (подписи к кнопкам с визуальными иконками, например) через .visually-hiiden. Альтернативно можно ещё использовать aria-label и aria-labeledby.
4. Добавляешь ещё больше визуально скрытой избыточной информации:
- Есть кнопка с иконкой? Впихни внутрь скрытый текст с описанием того, что она делает.
- Есть всплывающая на hover подсказка? Впихни текст подсказки прямо скрытым текстом рядом с элементом, саму всплывающую подсказку сделай aria-hidden. Карусель / список вкладок? просто вываливаешь весь контент разом, не пытаешься реализовать их. Вот это всё - чисто визуальные элементы, я уверен, они плохо воспринимаются, если не видишь их глазами.
- Кнопка-переключатель? Используй чекбокс и забей. Ну ладно, тут можно альтернативно заюзать aria-pressed. Но вообще, если нужен какой-то нестандартный элемент или нужно полностью заменить стандартный, то самое простое - повесить aria-hidden на свой велосипед и с клавиатуры сделать доступным нормальный HTML элемент (как я делал выше с кастомным селектом). Выше кидал статью про такой способ.
Например, пускай хочется сделать input[type=range] с двумя кружочками, чтобы выбирать промежуток между двумя значениями. Может быть полезно для фильтра по ценам, например. С клавиатуры и для скринридеров можно просто показать два обычных инпута с одним кружочком, которые будут синхронизированы с кастомным инпутом, и всё.
Тогда в теории тебе вообще никакие aria атрибуты, кроме aria-hidden, не понадобятся. И это должно выглядеть не так уж и плохо. А пердолинг с ролями, другими ариа-атрибутами скорее сделает всё только хуже, если что-то неправильно реализуешь.
https://developer.mozilla.org/en-US/docs/Web/HTML/Microdata
Способ аннотировать свой HTML какой-то дополнительной семантикой. Вроде как это относится к базовой SEO оптимизации. Берётся какая-то схема пример http://schema.org/SoftwareApplication вешается на какой-то элемент через itemscope+itemtype, на вложенные элементы вешается itemprop (причём они сами могут быть какими-то составными значениями).
Ещё есть метатеги всякие: author, keywords и description - самые основные. Но ещё есть вот такое:
https://ogp.me
Ещё дополнительная мета-информация о сайте. Может использоваться, например, когда вставляешь ссылку на сайт в какой-то соцсети, и она отображается как карточка, контент для которой берётся как раз из этих мета-тегов. Кто-то добавляет свои мета-теги для этих же целей:
https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
В HTML, помимо секционных элементов, есть ещё очень много всяких других семантичных тегов. Не все одинаково полезны, но вот достойные упоминания:
- <figure>+<figcaption> - какая-то иллюстрация, возможно, небольшой отрывок текста или цитата, с подписью.
- Семантичные теги для таблиц вроде <caption>, <thead> (полностью оборачивает шапку в отличие от <th>), <tbody>, <tfoot> (тут может быть summary, например). Пример таблицы, свёрстанной с ними: https://github.com/mdn/learning-area/blob/main/css/styling-boxes/styling-tables/punk-bands-complete.html
- <dl>, <dt>, <dd> - работают как отображение из одних значений (<dt>) в другие (<dd>). Подходят там, где таблица избыточна (таблицы отображают пару каких-то значений в одно, но иногда нужно описать соответствие между просто парами значений). Например, характеристики какого-нибудь товара в магазине.
- <em> vs <i>, <strong> vs <b> - первые обладают семантикой, вторые - только для выделения текста.
- <time> для временной отметки. Если внутри человеческое обозначение какого-то момента времени (например, "вчера"), то дополнительно использовать атрибут datetime.
- <address> для контактной информации. И тут стоит ещё вспомнить, что в href можно писать значения "..." и "tel:...". С телефона второй, например, сразу откроет приложение телефона и введёт номер. Алсо можно по-разному их стилизовать через селектор a[href^=""], например, добавить иконку какую-нибудь. Для ввода самих этих значений можно использовать input[type=tel] и input[tyle=email] - у них есть валидация по умолчанию и с телефона открывается клавиатура специальная. Можно, кстати, переопределить валидацию по умолчанию через атрибут pattern, там просто регулярка указывается.
- <q>, <blockquote> и <cite> для цитат
- <fieldset>+<legend>
- <progress> и <meter> (последний менее полезен)
- <datalist>
- <optgroup>
https://ratiobuddy.com
Интересный хак с тем, чтобы задать размер картинки как w100%+pt56.25%, например, чтобы сделать блок, подстраивающийся под ширину родителя с соотношением сторон 16:9 в этом случае. Можно использовать для картинок, чтобы у них сохранялось соотношение сторон (плюс object-fit for good measure, конечно).
Либо использовать такие aspect-ratio боксы для произвольного контента, но тогда, чтобы не задавать конкретную высоту на родителе, нужно повесить этот паддинг на ::before, а родителя сделать display: flex в комментариях https://codepen.io/lunelson/pen/yXeWrX В статье более мудрёный вариант с тем, чтобы сделать ::before float left + добавить ::after clearfix (display: flow-root тоже сработает), но зато на родителя никаких дополнительных ограничений.
https://polished.js.org/docs/#between
https://css-tricks.com/between-the-lines
Это тоже интересная идея - интерполировать всякие величины (размеры шрифтов, отступы и прочее) между брейкпоинтами, чтобы между брейкпоинтами всё было более адаптивным. Не было такой проблемы, что чуть-чуть осталось до брейкпоинта, из-за чего на маленьком экране пропорционально слишком большие отступы могут быть, например.
https://codepen.io/anonanon123/full/OJxJjXL
Какой же это бред, лол. Но иногда 3д эффекты могут выглядеть неплохо, мне кажется.
https://codepen.io/kevinpowell/pres/a60d44c86df49ed1baa3a0a230158885
Мне нравится дизайн такой переворачивающейся карточки, например. Можно ей ещё добавить 3д эффект небольшого поворота на hover мышкой в зависимости от положения мышки. Он ещё использует background-blend-mode, чтобы высветлить картинку за текстом, не знал о таком.
агрессивный старикашка, фи
>с сучьими людьми
сучьи люди для тебя научились передавать информацию по кабелю и оцифровывать. сучьи люди провели тебе интернет в дом, чтобы ты развлекался. сучьи люди топят в котельной, чтобы у тебя было тепло в доме. сучьи люди готовят тебе продукты на производстве. сучьи люди охраняют тебя от террористов-исламистов-фанатиков. сучьи люди снимают для тебя кино и делают игры, чтобы ты опять же развлекался.
а ты? ленивая пиявка. боишься? потому что вычислят, кто ты
Решил очень костыльно:
- На маленьком экране, когда меню закрыто, я вешаю на него opacity 0. Если открываешь меню, то он сразу же переключает opacity 1 и делает анимацию выезжания. Если закрываешь, то opacity переключается на 0 с задержкой, чтобы анимация заезжания обратно успела переключиться.
- На большом экране ставлю у этого меню opacity 0, но тк его всё равно надо показать (контент в хедере - это это же самое меню, просто расплющенное), то я делаю animation forwards для opacity от 0 до 1 с нулевой длительностью. И за счёт этого, когда экран обратно уменьшаешь, opacity не анимируется и не видно транзишена, который происходит обычно при заезжании меню вправо.
Я на секунду подумал, что, наверное, проще было бы вообще убрать транзишены и сделать всё это на анимациях, но попробовал, и как-то не получается: сталкиваюсь с той же проблемой, которую выше описал. Только тут я уже не знаю, как это починить. Ещё и дополнительно анимация заезжания направо проигрывается при загрузке страницы.
Тебе б таблеток попить, почилить, а не вот эти вот конспекты писать, с технологиями, которых на реальном проекте не увидишь - жить было бы проще, веселей.
Чё тебя так стриггерило на сучьих людей, лол. Я не имел ввиду, что я там лучше кого-то, если ты так это понял, я говорил только про то, что меня общение с людьми ирл напрягает.
И мне как-то всё равно, кто там что делает для моего незаслуженного комфорта. Если кому-то не нравится моё бытие пиявкой, это не мои проблемы, пускай сам меня руками отдирает.
>>555152
Не хочу я ничего, отстань.
>Я не имел ввиду
Держи в курсе
>это не мои проблемы, пускай сам меня руками отдирает
тебя уже отодрали
сдохнет мамка - пойдешь бомжевать
1920x1050, 0:35
Вроде доделал десктопную версию. С этим, наверное, пока что всё.
1920x1050, 0:41
>>547278
>- переключатель светлой / тёмной тем
>- отменять предыдущие запросы
>- ленивая подгрузка картинок и данных о фильмах
Переписал функцию, которая делает запросы на два хука (один для списка фильмов, другой - для дополнительной информации о конкретном фильме) с внутренним состоянием. Но не стал делать подгрузку пачками по 4 штуки, и так сойдёт.
Картинки ещё не доделал: нужно переписать карточку, чтобы фоновая картинка была сделана не через background-image, а через <picture>, чтобы она не грузилась на маленьких экранах + чтобы можно было повесить loading="lazy".
>- загрузка следующей страницы с результатами
И в целом переписал некоторые вещи, вынес что-то в контекст, но всё ещё по-хорошему надо отрефакторить кое-что.
Ещё переделал сам список фильмов с грида на что-то вроде велосипедного masonry. Изначально сделал columns, но они походу забагованные очень сильно в хроме (в файрфоксе работает), он некоторые списки карточек вообще не может нормально отрендерить почему-то. Поэтому я просто сделал два флексбокса, которые иногда меняю на display contents, чтобы отображать только одну колонку. Колонки неодинаковой высоты, я на счёт этого не парился, просто одинаковое количество карточек в каждую кладу.
>>554033
Для intersection обзёрвера пришлось пробрасывать ref внутрь карточки с фильмом, видимо, вот это основной юзкейс проброса ссылки: для intersection / resize / mutation обзёрверов.
Полистал немного доки редакса, сам ещё руками не пробовал, я был немного не прав на счёт него. Вместе с redux toolkit он выглядит удобным. Можно разбить редюсер на слайсы и он сам его соберёт в одну редюсер-функцию, не нужно самому прописывать switch по экшенам. И он сам сгенерит функции, которые создают экшены. И там ещё встроен внутри сразу immer для иммутабельных изменений состояния.
Не очень понял пока что, как там делаются асинхронные вещи, там есть thunk middleware и более новый RTK query, пока что не разбирался с ними. Последний вроде очень удобен тем, что очень много бойлерплейта внутри себя реализует, какой-нибудь CRUD вообще очень легко написать с ним:
https://redux-toolkit.js.org/rtk-query/usage/mutations#advanced-mutations-with-revalidation
Но он именно, чтобы фетчить данные, как я понял.
Ещё есть какой-то redux saga middleware, он вроде тоже для асинхронщины, но точно появился раньше RTK query и он не только для того, чтобы делать запросы. И я его видел в требованиях на некоторые вакансии.
1920x1050, 0:41
>>547278
>- переключатель светлой / тёмной тем
>- отменять предыдущие запросы
>- ленивая подгрузка картинок и данных о фильмах
Переписал функцию, которая делает запросы на два хука (один для списка фильмов, другой - для дополнительной информации о конкретном фильме) с внутренним состоянием. Но не стал делать подгрузку пачками по 4 штуки, и так сойдёт.
Картинки ещё не доделал: нужно переписать карточку, чтобы фоновая картинка была сделана не через background-image, а через <picture>, чтобы она не грузилась на маленьких экранах + чтобы можно было повесить loading="lazy".
>- загрузка следующей страницы с результатами
И в целом переписал некоторые вещи, вынес что-то в контекст, но всё ещё по-хорошему надо отрефакторить кое-что.
Ещё переделал сам список фильмов с грида на что-то вроде велосипедного masonry. Изначально сделал columns, но они походу забагованные очень сильно в хроме (в файрфоксе работает), он некоторые списки карточек вообще не может нормально отрендерить почему-то. Поэтому я просто сделал два флексбокса, которые иногда меняю на display contents, чтобы отображать только одну колонку. Колонки неодинаковой высоты, я на счёт этого не парился, просто одинаковое количество карточек в каждую кладу.
>>554033
Для intersection обзёрвера пришлось пробрасывать ref внутрь карточки с фильмом, видимо, вот это основной юзкейс проброса ссылки: для intersection / resize / mutation обзёрверов.
Полистал немного доки редакса, сам ещё руками не пробовал, я был немного не прав на счёт него. Вместе с redux toolkit он выглядит удобным. Можно разбить редюсер на слайсы и он сам его соберёт в одну редюсер-функцию, не нужно самому прописывать switch по экшенам. И он сам сгенерит функции, которые создают экшены. И там ещё встроен внутри сразу immer для иммутабельных изменений состояния.
Не очень понял пока что, как там делаются асинхронные вещи, там есть thunk middleware и более новый RTK query, пока что не разбирался с ними. Последний вроде очень удобен тем, что очень много бойлерплейта внутри себя реализует, какой-нибудь CRUD вообще очень легко написать с ним:
https://redux-toolkit.js.org/rtk-query/usage/mutations#advanced-mutations-with-revalidation
Но он именно, чтобы фетчить данные, как я понял.
Ещё есть какой-то redux saga middleware, он вроде тоже для асинхронщины, но точно появился раньше RTK query и он не только для того, чтобы делать запросы. И я его видел в требованиях на некоторые вакансии.
на это дофига времени уходит, а по факту бесплезная фигня (я про реакт и css, да и высокоуровневый веб в целом). поэтому тебе не хочется этим заниматься, понимаю. результат хороший
>>557016
>Не очень понял пока что, как там делаются асинхронные вещи
вариант 1
1. делаешь запрос
2. получаешь ответ
3. диспатчишь после получения
псевдокод:
const dispatch = useDispatch();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
API.fetch(data, dispatch)
.then(_ => setLoading(false))
}, [])
if (isLoading) return <Loader />;
.....
вариант 2
1. диспатчишь в асинхронный экшн через thunk
2. дальше как в первом варианте
вариант 3
1. диспатчишь экшн
2. экшен перехватываешь сагой
3. в саге делаешь все тоже самое, что в первом варианте
вывод
и так и сяк одинаково. сага просто разделяет приложение. экшены - отдельно, сайд эффекты - отдельно. больше писанины будет. разделение логики актуально только для больших приложений, когда, наппример, у тебя что-то крякнулось и лезешь в конкретный файл, чтобы пофиксить (или отдебажить) конкретную проблему.
>>557016
>Не очень понял пока что, как там делаются асинхронные вещи
вариант 1
1. делаешь запрос
2. получаешь ответ
3. диспатчишь после получения
псевдокод:
const dispatch = useDispatch();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
API.fetch(data, dispatch)
.then(_ => setLoading(false))
}, [])
if (isLoading) return <Loader />;
.....
вариант 2
1. диспатчишь в асинхронный экшн через thunk
2. дальше как в первом варианте
вариант 3
1. диспатчишь экшн
2. экшен перехватываешь сагой
3. в саге делаешь все тоже самое, что в первом варианте
вывод
и так и сяк одинаково. сага просто разделяет приложение. экшены - отдельно, сайд эффекты - отдельно. больше писанины будет. разделение логики актуально только для больших приложений, когда, наппример, у тебя что-то крякнулось и лезешь в конкретный файл, чтобы пофиксить (или отдебажить) конкретную проблему.
Когда-нибудь в этом разделе будут банить за нытьё...
1920x1050, 0:41
Доделал тут клавиатурную навигацию, добавил недостающие аутлайны на :focus. Это ужасно, её нереально адекватно сделать. В общем, я просто повесил на все focusable элементы внутри всплывающих меню и окон tabindex=-1 и потом в нужные моменты делаю у них tabindex=0 и трапую фокус при необходимости вот этим https://www.npmjs.com/package/focus-trap Если активировать ловушку, то оно само запоминает последний сфокусированный элемент и переключается на него после деактивации.
Иногда происходят странные вещи, можно пофиксить, если делать не просто focus(), а focus({ preventScroll: true }). Когда делаю фокус на выезжающем подменю (внутри бургерного на маленьком экране), то анимация проигрывается очень всрато, короче, не понял, как решить, просто сделал setTimeout на фокус, чтобы анимация успела отыграть. Но так, наверное, не стоит делать вообще.
Столкнулся с неприятной проблемой: mask-image скрывает аутлайн. Я почему-то думал, что он остаётся. Я просто mask-image для иконок использую обычно, чтобы их можно было перекрашивать. Решается только добавлением ещё одного тега в HTML походу.
:focus-within местами удобно может быть для этого. Вот в списке ссылок внизу на маленьком экране, например.
В одном месте неправильный порядок фокусов получился из-за того, что на маленьком экране порядок один, а на большом - другой. Наверное, адекватно (не выставляя tabindex > 0) никак не пофиксить.
Не знаю, как я до этого не нарывался на проблемы из-за этого, только сейчас.
Доделал, надеюсь, до конца уже (в любом случае больше не буду к ней прикасаться) ту страничку старбакса (пофиксил несколько багов с клавиатурной навигацией и пару визуальных вещей, недостающие скроллбары для горизонтальной ориентации телефона).
Бесит, что так много всяких мелких недочётов, которые так легко упустить из вида, даже на настолько простой странице. Причём это не просто какая-то визуально некрасивая ерунда, а что-то, что делает страницу просто неюзабельной. Например, если того же скроллбара где-то не хватает, или когда из-за фокуса сбрасываются трансформы, или когда с костыльным focus-trap что-то не то происходит и полностью ломается клавиатурная навигация.
Не знаю, наверное, с меня хватит вёрстки пока что.
Начал делать какую-то ерунду с бэком на экспрессе, чтобы у приложения внешнее состояние было какое-то, не только локально на клиенте. Короче, какой-нибудь CRUD будет. Пока что ничего почти не сделал, только JWT-аутентификацию по захардкоженным в беке паролю и юзернейму. С бэкендом, естественно, подробно не разбираюсь и не пытаюсь сделать что-то адекватное, просто копирую код из интернета, лишь бы как-то работало.
>JWT-аутентификацию по захардкоженным в беке паролю и юзернейму
Так по-идиотски звучит. Я имел ввиду, что авторизация по захардкоженным логину и паролю, сервер отдаёт токен по ним. И JWT аутентификация.
1920x1050, 0:48
Была идея, как отделить список фильмов как отдельный компонент: сделать его тупой вьюшкой и чтобы она дёргала коллбэк, который ей даёшь, когда она хочет больше фильмов (когда долистываешь до конца). Но уже лень пробовать делать, чтобы посмотреть, как оно будет выглядеть.
>>547278
>- добавить возможность добавлять в избранное и смотреть список избранных фильмов, сохранять его в local storage
Ещё доделал ленивые фоновые картинки у карточек (чтобы не грузились на мелких экранах), обработку ошибок, если запрос зафейлился, кнопку, которая скроллит вверх, фавиконки.
я большую часть времени смотрю в монитор и ничего не делаю, я в ступоре я не могу больше, я просто хочу много спать и ничего не делать мне не нужно это всё
вот просто что это должно означать вообще, выглядит как бред, а оно делает так, что юнион тип T = { one: '1', two: '2' } | { one: '1' } | { one: '1', two: '2', three: '3' } превращает в 'one' | 'two' | 'three'.
Вроде когда юнион вставляешь, то keyof T применяется к каждому элементу юниона и из результата делается юниони. Поэтому так работает.
Ещё какие-то mapped типы есть
Middleware для стора - это просто функция, которая перехватывает диспатчи и внутри может прокинуть экшн дальше. И middleware - это в том числе место, где предполагается, что ты будешь делать все сайд-эффекты и асинхронные вещи. Потому что редюсер должен быть в идеале чистой функцией, наверное, чтобы проще тестировать его было.
Вместо того, чтобы писать отдельный middleware на каждый экшн, который должен вызывать сайд-эффекты, можно юзать thunk middleware, который, если видит, что ему попалась функция (thunk) вместо экшена, вызывает её, передавая внутрь доступ к стору и диспатчу. И из thunkа ещё можно вернуть значение, которое потом вернётся, когда будешь диспатчить thunk (по умолчанию без thunk middleware из диспатча возвращается просто экшн, который ты ему только что отдал),
https://redux.js.org/api/applymiddleware#example-using-thunk-middleware-for-async-actions
чтобы можно было вернуть промис и чейнить диспатчи, видимо. Выглядит плохо, потому что thunkи написаны как обычные функции, а не async, с ними было бы нормально.
В redux toolkit есть createAsyncThunk, с ним немного проще писать thunkи. Он создаёт thunk action creator + экшн creatorы для pending, fulfilled, rejected, которые можно впихнуть внутрь extraReducers у слайса, чтобы менять состояние в зависимости от того, что происходит с thunkом.
extraReducers в слайсе - это то же самое, что и reducers, но он не создаёт экшн creatorов и может обрабатывать экшены, определённые в других слайсах или просто определённые отдельно.
https://redux-toolkit.js.org/api/createAsyncThunk#unwrapping-result-actions
И когда диспатчишь thunk, созданный через createAsyncThunk, то тоже возвращается промис, но там почему-то сделали так, что возвращается не оригинальный промис, а объект с методом unwrap(), который уже возвращает нужный промис.
А redux saga - это тоже middleware, тут watcher сага перехватывает экшены и те, которые хочешь, можно перенаправить в worker сагу, которая делает все сайд-эффекты. И там саги - это генераторные функции, из которых ты yieldишь инструкции для middleware (эффекты). То есть саги - что-то вроде последовательности инструкций.
Там эффекты по типу put - задиспатчить экшн, call и apply - вызвать какую-то функцию. Плюс такого подхода в том, что саги довольно легко тестировать, потому что сами по себе они никаких осмысленных действий не выполняют.
И я не знал, что в .next() генератору можно передавать значение, которое вернётся из yield внутри функции. И ещё через .throw() можно выбросить исключение внутрь функции. Так что можно мокать то, что возвращает call внутри саги, например. Как тут в примере ниже https://redux-saga.js.org/docs/basics/DispatchingActions
Эффекты там есть блокируюшие и неблокирующие. take и call - блокирующие эффекты, то есть когда saga middleware будет выполнять их, в первом случае она будет ждать, когда задиспатчится экшн определённого типа, во втором - ждать, пока выполнится функция. Для неблокирующих вызовов есть fork/join и spawn. Разница между fork и spawn в том, что второй вообще отдельно живёт от дерева вызовов саг и не блокает родительскую сагу.
Ну и takeEvery/takeLatest/takeLeading для неблокирующей обработки экшенов. Они довольно очевидно реализуются через более лоулевельные эффекты https://redux-saga.js.org/docs/api/#notes-3
https://youtu.be/ah5voE_SGjo
Внезапно нормальное to the point видео.
Middleware для стора - это просто функция, которая перехватывает диспатчи и внутри может прокинуть экшн дальше. И middleware - это в том числе место, где предполагается, что ты будешь делать все сайд-эффекты и асинхронные вещи. Потому что редюсер должен быть в идеале чистой функцией, наверное, чтобы проще тестировать его было.
Вместо того, чтобы писать отдельный middleware на каждый экшн, который должен вызывать сайд-эффекты, можно юзать thunk middleware, который, если видит, что ему попалась функция (thunk) вместо экшена, вызывает её, передавая внутрь доступ к стору и диспатчу. И из thunkа ещё можно вернуть значение, которое потом вернётся, когда будешь диспатчить thunk (по умолчанию без thunk middleware из диспатча возвращается просто экшн, который ты ему только что отдал),
https://redux.js.org/api/applymiddleware#example-using-thunk-middleware-for-async-actions
чтобы можно было вернуть промис и чейнить диспатчи, видимо. Выглядит плохо, потому что thunkи написаны как обычные функции, а не async, с ними было бы нормально.
В redux toolkit есть createAsyncThunk, с ним немного проще писать thunkи. Он создаёт thunk action creator + экшн creatorы для pending, fulfilled, rejected, которые можно впихнуть внутрь extraReducers у слайса, чтобы менять состояние в зависимости от того, что происходит с thunkом.
extraReducers в слайсе - это то же самое, что и reducers, но он не создаёт экшн creatorов и может обрабатывать экшены, определённые в других слайсах или просто определённые отдельно.
https://redux-toolkit.js.org/api/createAsyncThunk#unwrapping-result-actions
И когда диспатчишь thunk, созданный через createAsyncThunk, то тоже возвращается промис, но там почему-то сделали так, что возвращается не оригинальный промис, а объект с методом unwrap(), который уже возвращает нужный промис.
А redux saga - это тоже middleware, тут watcher сага перехватывает экшены и те, которые хочешь, можно перенаправить в worker сагу, которая делает все сайд-эффекты. И там саги - это генераторные функции, из которых ты yieldишь инструкции для middleware (эффекты). То есть саги - что-то вроде последовательности инструкций.
Там эффекты по типу put - задиспатчить экшн, call и apply - вызвать какую-то функцию. Плюс такого подхода в том, что саги довольно легко тестировать, потому что сами по себе они никаких осмысленных действий не выполняют.
И я не знал, что в .next() генератору можно передавать значение, которое вернётся из yield внутри функции. И ещё через .throw() можно выбросить исключение внутрь функции. Так что можно мокать то, что возвращает call внутри саги, например. Как тут в примере ниже https://redux-saga.js.org/docs/basics/DispatchingActions
Эффекты там есть блокируюшие и неблокирующие. take и call - блокирующие эффекты, то есть когда saga middleware будет выполнять их, в первом случае она будет ждать, когда задиспатчится экшн определённого типа, во втором - ждать, пока выполнится функция. Для неблокирующих вызовов есть fork/join и spawn. Разница между fork и spawn в том, что второй вообще отдельно живёт от дерева вызовов саг и не блокает родительскую сагу.
Ну и takeEvery/takeLatest/takeLeading для неблокирующей обработки экшенов. Они довольно очевидно реализуются через более лоулевельные эффекты https://redux-saga.js.org/docs/api/#notes-3
https://youtu.be/ah5voE_SGjo
Внезапно нормальное to the point видео.
Я не понимал, что в реакте есть разделение на rendering phase и commit phase. Первое - это то, где реакт составляет дифф VDOMа и определяет, что нужно апдейтнуть, commit phase - то, где реакт применяет изменения к DOMу.
В связи с этим понятнее разница между useEffect и useLayoutEffect, componentDidCatch и getDerivedStateFromError. Первые происходят асинхронно после фазы коммита, вторые - синхронно в фазе рендера, перед коммитом.
https://react-redux.js.org/tutorials/connect
https://youtu.be/gFZiQnM3Is4
На всякий случай посмотрел, как выглядит connect в редаксе. В общем, само приложение всё так же оборачивается в Provider, а connect - это просто HOC, который принимает на вход дополнительно mapStateToProps и mapDispatchToProps. Я так понял, что вообще этот дополнительный слой нужен чисто для того, чтобы определить, какие компоненты будут подписываться на изменения в сторе, а какие - нет (передать null в mapStateToProps). Теперь это через хук useSelector делается просто, да.
https://redux.js.org/usage/structuring-reducers/normalizing-state-shape
https://redux.js.org/usage/structuring-reducers/updating-normalized-data
Про нормализацию стейта в редаксе. Типа избегать повторений в стейте, избегать вложенности, чтобы при иммутабельных изменениях стейта не делалось лишних ререндеров из-за того, что лишние объекты изменились. Отделять сущности друг от друга, идентифицировать их через айдишки, ссылаться друг на друга через них же, дополнительные "таблицы" для many-to-many отношений. Ну примерно как с нормализацией в бд получается.
https://github.com/redux-orm/redux-orm
Там ещё вот эта дичь упоминается, чтобы было удобнее работать со стейтом, организованным как база данных. Но она вроде не снискала особо популярности. Я вообще сомневаюсь, что редакс стейт может быть в реальности настолько сложным, что нужно к нему прикручивать такую абстракцию.
К тому же есть вроде apollo client, который частично отбрасывает необходимость в редаксе в принципе в контексте хранения fetched данных, потому что apollo кеширует их сам. И это вроде не только если бэк с GraphQL, но и с рест апи вроде тоже можно заставить его работать. Но я про всё это почти ничего не знаю, только саму идею, что в отличие от рест апи с GraphQL можно фетчить с сервера только те данные, которые тебе нужны, а не всё подряд, что выплёвывает эндпоинт.
https://redux-toolkit.js.org/api/createEntityAdapter
Ещё такое есть, но это чисто для устранения бойлерпрплейта с работой с сущностями в сторе по айдишкам.
https://github.com/paularmstrong/normalizr
Либа для нормализации json объектов.
https://redux-saga.js.org/docs/advanced/Channels
Ещё немного посмотрел про редакс сага, конкретно про каналы (actionChannel, eventChannel, channel). Можно складывать экшены из редакса или события из какого-то другого источника (там пример с сокетами) в буфер и постепенно их выполнять. Можно ещё создать пул саг, которым отдавать на обработку какие-то данные через channel, но не очень понял, для чего это нужно, разве что, чтобы ограничить количество саг, которые что-то делают, наверное.
https://redux-saga.js.org/docs/api#debouncems-pattern-saga-args
Ещё есть хелперы throttle и debounce. Throttle берёт последний экшен из пришедших (использует actionChannel с buffers.sliding(1)), запускает его обработку и блокается на какое-то время, потом снова. Debounce ждёт либо, пока не выйдет время, либо пока не прийдёт новый экшен, и если вышло время, то обрабатывает последний пришедший экшен, а если пришёл новый экшен, то снова начинает ждать.
В общем, если есть, например, текстовое поле для поиска и экшены диспатчатся на каждый введённый символ, а обрабатываются они так, что, например, делается какой-то запрос и выводится список подсказок как в поиске гугла. То в случае с throttle список подсказок будет обновляться раз в N секунд, пока ты печатаешь, а с debounce обновится через N секунд после того, как перестанешь печатать.
https://redux-saga.js.org/docs/advanced/TaskCancellation
Ещё про cancelled не знал, можно выполнять какую-то логику, когда сагу отменяют откуда-то извне (при использовании takeLatest, debounce, throttle, например), например, чтобы отменить запрос, ну в целом какой-то cleanup выполнить.
В целом примерно понятно, короче, что может эта либа.
Я не понимал, что в реакте есть разделение на rendering phase и commit phase. Первое - это то, где реакт составляет дифф VDOMа и определяет, что нужно апдейтнуть, commit phase - то, где реакт применяет изменения к DOMу.
В связи с этим понятнее разница между useEffect и useLayoutEffect, componentDidCatch и getDerivedStateFromError. Первые происходят асинхронно после фазы коммита, вторые - синхронно в фазе рендера, перед коммитом.
https://react-redux.js.org/tutorials/connect
https://youtu.be/gFZiQnM3Is4
На всякий случай посмотрел, как выглядит connect в редаксе. В общем, само приложение всё так же оборачивается в Provider, а connect - это просто HOC, который принимает на вход дополнительно mapStateToProps и mapDispatchToProps. Я так понял, что вообще этот дополнительный слой нужен чисто для того, чтобы определить, какие компоненты будут подписываться на изменения в сторе, а какие - нет (передать null в mapStateToProps). Теперь это через хук useSelector делается просто, да.
https://redux.js.org/usage/structuring-reducers/normalizing-state-shape
https://redux.js.org/usage/structuring-reducers/updating-normalized-data
Про нормализацию стейта в редаксе. Типа избегать повторений в стейте, избегать вложенности, чтобы при иммутабельных изменениях стейта не делалось лишних ререндеров из-за того, что лишние объекты изменились. Отделять сущности друг от друга, идентифицировать их через айдишки, ссылаться друг на друга через них же, дополнительные "таблицы" для many-to-many отношений. Ну примерно как с нормализацией в бд получается.
https://github.com/redux-orm/redux-orm
Там ещё вот эта дичь упоминается, чтобы было удобнее работать со стейтом, организованным как база данных. Но она вроде не снискала особо популярности. Я вообще сомневаюсь, что редакс стейт может быть в реальности настолько сложным, что нужно к нему прикручивать такую абстракцию.
К тому же есть вроде apollo client, который частично отбрасывает необходимость в редаксе в принципе в контексте хранения fetched данных, потому что apollo кеширует их сам. И это вроде не только если бэк с GraphQL, но и с рест апи вроде тоже можно заставить его работать. Но я про всё это почти ничего не знаю, только саму идею, что в отличие от рест апи с GraphQL можно фетчить с сервера только те данные, которые тебе нужны, а не всё подряд, что выплёвывает эндпоинт.
https://redux-toolkit.js.org/api/createEntityAdapter
Ещё такое есть, но это чисто для устранения бойлерпрплейта с работой с сущностями в сторе по айдишкам.
https://github.com/paularmstrong/normalizr
Либа для нормализации json объектов.
https://redux-saga.js.org/docs/advanced/Channels
Ещё немного посмотрел про редакс сага, конкретно про каналы (actionChannel, eventChannel, channel). Можно складывать экшены из редакса или события из какого-то другого источника (там пример с сокетами) в буфер и постепенно их выполнять. Можно ещё создать пул саг, которым отдавать на обработку какие-то данные через channel, но не очень понял, для чего это нужно, разве что, чтобы ограничить количество саг, которые что-то делают, наверное.
https://redux-saga.js.org/docs/api#debouncems-pattern-saga-args
Ещё есть хелперы throttle и debounce. Throttle берёт последний экшен из пришедших (использует actionChannel с buffers.sliding(1)), запускает его обработку и блокается на какое-то время, потом снова. Debounce ждёт либо, пока не выйдет время, либо пока не прийдёт новый экшен, и если вышло время, то обрабатывает последний пришедший экшен, а если пришёл новый экшен, то снова начинает ждать.
В общем, если есть, например, текстовое поле для поиска и экшены диспатчатся на каждый введённый символ, а обрабатываются они так, что, например, делается какой-то запрос и выводится список подсказок как в поиске гугла. То в случае с throttle список подсказок будет обновляться раз в N секунд, пока ты печатаешь, а с debounce обновится через N секунд после того, как перестанешь печатать.
https://redux-saga.js.org/docs/advanced/TaskCancellation
Ещё про cancelled не знал, можно выполнять какую-то логику, когда сагу отменяют откуда-то извне (при использовании takeLatest, debounce, throttle, например), например, чтобы отменить запрос, ну в целом какой-то cleanup выполнить.
В целом примерно понятно, короче, что может эта либа.
И мне стоило бы, наверное, пытаться вкатываться в собеседования, но мне, блин, страшно и я с самого начала не хотел ничего делать в этом направлении. Я хотел лежать и ничего не делать.
Наверное, в качестве последней прокрастинационной задачи посмотрю, что такое бутстрап и попробую на нём сверстать страничку со ссылками и скринами на все мои два с половиной пет пРоЕкТа, дальше не знаю.
Мне страшно разговаривать с кем-то, я реально даже не запинаюсь, меня вопросы, адресованные ко мне, просто в ступор вводят, внутри голова вычищается и я тупо молчу в ответ. Кто угодно справедливо распознает во мне умыстенно отсталого и не захочет иметь никаких дел. Я не знаю, как мимикрировать под адекватного человека.
И у меня сложилось стойкое ощущение, что дебилы без опыта вроде меня сейчас никому не нужны, и можно даже не пытаться.
И даже если я чудом куда-то попаду, то каковы шансы, что я выдержу 9-часовые ежедневные сессии занятия чем-то хоть сколько-нибудь осмысленным. И с учётом того, что я в своей жизни бросал примерно всё на начальных этапах.
Забавная фича, я не знал о ней.
УЧИШЬ REACT, JS, TYPESCRIPT, HTML/CSS ДАЖЕ НЕБО, ДАЖЕ АЛЛАХА, ЧТОБЫ ВКАТИТЬСЯ В РАБОТУ
@
ПРЕВОЗМОГАЕШЬ ЛЕНЬ И БЕССИЛИЕ
@
ТАК, ВРОДЕ БЫ Я ГОТОВ ИДТИ НА СОБЕСЕДОВАНИЕ
@
ВСПОМИНАЕШЬ, ЧТО ТЫ СОЦИОФОБ-АУТИСТ С НАБОРОМ ПСИХИЧЕСКИХ РАССТРОЙСТВ И НЕ МОЖЕШЬ ВО ВЗАИМОДЕЙСТВИЕ С ЛЮДЬМИ
@
ЖИДКО ПЕРНУВ, УМИРАЕШЬ
Да нормчо, зойчем такой пессимизм. У меня вон кроме первого и последнего пункта все совпало, и ничо, мимикрирую под ОЙТИШНЕГА уже пятнадцатый год
>Наверное, в качестве последней прокрастинационной задачи посмотрю, что такое бутстрап
Бутстрап не нужен, сейчас все юзают tailwind
https://2021.stateofcss.com/en-US/technologies
Не все. Бутстрап всё ещё популярный очень. И они всё же разные по своей сути: бутстрап про готовые компоненты, тейлвинд про утилитарные классы. Например, если мне нужно будет склепать какой-то плейсхолдерный UI, то бутстрап лучше подойдёт.
>>562427
Я не социофоб, я просто безнадёжное чмо.
>Например, если мне нужно будет склепать какой-то плейсхолдерный UI, то бутстрап лучше подойдёт.
https://tailwindui.com/
Послушал на x2 пару постановочных собеседований на джуниоров-фронтендеров на ютубе, там были либо примитивные вопросы, либо всякие шизовопросы по типу "чем отличается {...source} от Object.assign({}, source)" или "откуда берётся пробел между inline-block элементами". Короче, там какой-то бред нереалистичный, скорее всего.
По этому видео https://youtu.be/I6ypD7qv3Z8 прошёл два часа, оно на удивление всё ещё более-менее актуальное, хоть и больше года прошло, и всё более-менее осталось таким же из того, что пока что было. За исключением этого момента
https://stackoverflow.com/questions/70219951/typeerror-err-invalid-arg-type-express-sessionredis-error
Пока что просто сервер на экспрессе с graphQL. Постгрес, чтобы хранить юзеров, их посты и прочее такое, редис, чтобы хранить сессии. Можно регистрироваться, логиниться и смотреть своё имя (просто тест, что сессии работают). Через graphQL плейграунд. Там довольно простой, оказывается, синтаксис, ты как будто пишешь джейсон, но только ключи, без значений.
GraphQL схема и резолверы (это то, что query и mutation) описываются через такое https://typegraphql.com. И на классы для схем можно ещё навесить ещё и описание ORM сущностей, тоже через тайпскриптовые декораторы https://mikro-orm.io/docs/defining-entities
На пике ты?Нет, это Элла.