Тёмный

Правильные page layouts во Vue 

Мастерская разработчика
Просмотров 9 тыс.
50% 1

Видео посвящено анализу и разработке системы page layouts во Vue 3
⌛ Таймкоды ⌛
0:00 - Введение
0:10 - Обзор видео
1:01 - Что такое шаблоны?
2:17 - Требования к системе шаблонов
3:41 - ПРОСТО СЛОТЫ обзор подхода
4:19 - ПРОСТО СЛОТЫ реализация подхода
4:58 - ПРОСТО СЛОТЫ демонстрация, проблемы
6:18 - ВОТЧЕРЫ, КОМПЬЮТЕДЫ обзор подхода
8:00 - ВОТЧЕРЫ, КОМПЬЮТЕДЫ реализация подхода
9:12 - ВОТЧЕРЫ, КОМПЬЮТЕДЫ демонстрация, проблемы
12:04 - МИДЛВАРКА обзор подхода
13:01 - МИДЛВАРКА реализация подхода
14:13 - МИДЛВАРКА демонстрация
16:36 - Проверка выполнения требований
17:47 - Выводы
⚡ Ссылки ⚡
Презентация - slides.com/sticker0ne/vue-lay...
Репа гитлаба - gitlab.com/Sticker0ne/vue-lay...
Статья Manu - itnext.io/vue-tricks-smart-la...
Статья Edward - habr.com/ru/post/513728/
✨ Так же я и разработка ✨
Мой канал в телеграмме - t.me/developers_workshop
Мой инстаграм - / stick_one
#layouts #vue #typescript #vuejs #javascript #browser #layout #page #react #it #vite #development #webdev #web #js

Наука

Опубликовано:

 

2 июн 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 99   
@grefrewhtr
@grefrewhtr 15 дней назад
Сергей, большое спасибо вам за данное видео, оно прекрасно! Показана проблема, показаны разные варианты решения, их плюсы и минусы, разобрана реализация каждого подхода, идеально! Жаль, что вы делаете так мало контента, у вас определено талант!
@dev-workshop
@dev-workshop 13 дней назад
Большое спасибо, мне очень приятно!) Проблемы с распределением времени, нужны помощники в монтаже)
@user-vj8xc8st3i
@user-vj8xc8st3i 2 года назад
Полезная информация и хорошая подача, спасибо! Буду ждать новых видосов 🙃
@akad1981
@akad1981 Год назад
Это шикарно! Спасибо Сергей!
@dev-workshop
@dev-workshop Год назад
Очень приятно, спасибо!)
@jozefmaslovsky9270
@jozefmaslovsky9270 Год назад
Интересненько!!! Спасибо, тебе, добрый человек!
@dev-workshop
@dev-workshop Год назад
Рад, что понравилось!
@user-nf3gq3zh7r
@user-nf3gq3zh7r Год назад
Спасибо огромное - очень полезное видео!
@dev-workshop
@dev-workshop Год назад
Очень приятно, спасибо!
@brodyagaPATY
@brodyagaPATY Год назад
Зачет, спасибо!!!! На работе попробую))
@dev-workshop
@dev-workshop Год назад
Пожалуйста:) Отпиши как зайдет)
@edshamshurin6130
@edshamshurin6130 Год назад
Отличный и очень для меня актуальный видосик :) Огромная благодарность автору☺
@dev-workshop
@dev-workshop Год назад
Спасибо, большое! Очень приятно читать такие комментарии!
@victard7512
@victard7512 Год назад
Спасибо за видео) Подписался, надеюсь будут выходить такие ролики почаще)
@dev-workshop
@dev-workshop Год назад
Спасибо, за комментарий!) Подписывайся на телеграм канал, там переодически публикуется что-нибудь интересное по теме :) Я стараюсь выпускать видео чаще, но пока что получается не очень
@victard7512
@victard7512 Год назад
@@dev-workshop Уже подписался)
@ulyanov_life
@ulyanov_life 2 года назад
Хороший выпуск! Серег, очень жду разбор аккордиона!
@dev-workshop
@dev-workshop 2 года назад
Разбор аккордеона, так и запишем
@YarkiiYa
@YarkiiYa Год назад
Респект, очень классное видео!
@dev-workshop
@dev-workshop Год назад
Спасибо, очень рад!)
@benrise4775
@benrise4775 2 месяца назад
Шикарно!! Спасибо
@dev-workshop
@dev-workshop 2 месяца назад
Пожалуйста)
@albertsaitov7463
@albertsaitov7463 Год назад
Топич, спасибо большое за ролик
@dev-workshop
@dev-workshop Год назад
Рад, что понравилось)
@artemijeka
@artemijeka 10 месяцев назад
Спасибо автору! Круто когда люди делятся открытиями с обществом) Мне интересна тема для следующего видео) если конечно вопрос стоящий: насколько успешно поисковик считывает контент с SPA приложений и как лучше подавать контент для поисковика в vuejs?
@dev-workshop
@dev-workshop 10 месяцев назад
Привет! Спасибо!) Практически не на сколько. Хоть все и говорят, что вот вот индексаторы научатся в спа - это все не правда Все, что должно попасть в индексацию должно быть ssr
@olegycholegych1920
@olegycholegych1920 11 месяцев назад
ты лучший ❤
@xoxo2880808
@xoxo2880808 2 года назад
Спасибо, интересно, получил задачу реализовать динамические роуты на vue в зависимости от роли, которая приходит slug’ом от сервера, завтра попробую применить подобное, до этого все время на react проекты были :) на проекте вроде есть какая-то middleware, но я ещё детально не ковырял.
@dev-workshop
@dev-workshop 2 года назад
Рад, что видео понравилось!) По твоей формулировке, мне кажется, это называется security middleware или authorization guard, что-то подобное. Вот здесь есть абстрактный пример (третий сверху) router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards
@xoxo2880808
@xoxo2880808 2 года назад
@@dev-workshop по факту все оказалось проще, чем говорили. Layout все таки один, а меню, хедер и футер генерируют разное содержимое через store сами, я сделал по принципу как в примере из ссылки, только вешал на нужные роуты и через meta задавал массив ролей разрешённых.
@xeleos
@xeleos Год назад
супер!
@dev-workshop
@dev-workshop Год назад
Спасибо:)
@zergzerg4844
@zergzerg4844 Год назад
Не пойму к чему такие сложности. Можно же проще написать и принцип mount/unmount лайота с компонентами такой же будет: в App.vue в router.js (все компоненты пихаем в children нужного layout) const routes = [ { path: '/', name: 'baselayout', component: BaseLayout, meta:{ layout: BaseLayout }, children: [ { path: '/page1/', name: 'page1', component: () => import('@/views/Page1.vue') }, { path: '/page2', name: 'page2', component: () => import('@/views/Page2.vue') }, ] }, { path: '/guard', name: 'guard', component: () => import('@/views/guard/GuardIndex.vue'), meta:{ layout: AdminLayout }, children: [ { path: '/page3.', name: 'page3', component: () => import('@/views/Page2.vue') }, ] }, ]; в BaseLayout.vue (transition конечно здесь лишний. просто допом оставил) И все работает и при хождении по дочерним вьюшкам layout не размонтируется каждый раз, а только тогда пока перехожу на дочернюю вьюшку другого layout. Глюков с переходами при таком подходе пока не увидел. Автор, поправьте, если что-то не так с таким подходом, так как не очень хорошо шарю за vue. Спасибо за видео
@artemkomarov9902
@artemkomarov9902 Год назад
а есть такое эффект при использовании этой системы, сейчас опищу: в футоре сайта ссылка на страницу политики, соответственно я проскролил страницу далеко в низ. так вот при клике на ссылку я меняется страница и я остаюсь так же проскроденный внизу, как это исправить, чтобы новая страница открывалась с начала а не с того места где я был проскролен до клика по ссылке ??
@dev-workshop
@dev-workshop Год назад
Вариантов много, от кастомных мидлварок, до обратчиков в маунте странички. Но мне кажется, самый правильный вот этот router.vuejs.org/guide/advanced/scroll-behavior.html
@sakensatenov
@sakensatenov Год назад
Вопрос (оффтоп): у меня есть layout (шапка и футер) В котором есть компонент (страница с данными). В шапке тоже есть свои данные, все прекрасно работает. Но я хочу передать некоторые данные из чайлд компонента в layout, дабы отобразить инфу про страницу в layout. Не хочу лезть в vuex. Как можно передать данные из чайлда в layout?
@dev-workshop
@dev-workshop Год назад
Это плохая практика, лучше делать это каким-то отдельным инструментом. Но как вариант, можно воспользоваться либо ивентбасом Либо сделать синглтон композобл и воспользоваться им в шапке и на странице. Но это плохая практика, столкнетесь со многими проблемами :)
@sakensatenov
@sakensatenov Год назад
@@dev-workshop ок спасибо
@Atelier155
@Atelier155 Год назад
привет, а почему не работает с алиасом в мидлваре, если использую @ в пути функции import, то не работает?
@dev-workshop
@dev-workshop Год назад
Привет! Алиасы резолвятся веб паком или витом, в мидлварках не резолвятся, не копал почему. Так же в nuxt.config, например, не резолвятся. Нужно копат
@user-kl6be1qp3g
@user-kl6be1qp3g Год назад
Пытался, что-то подобное у себя написать не получилось. Может оформишь в виде плагина или дашь консультацию?
@dev-workshop
@dev-workshop Год назад
С плагином сложно, так как много специфики на каждом проекте, я лишь продемонстрировал общую идею. В видео есть ссылка на гитлаб, там рабочий проект его можно склонировать к себе и поковырять. Что именно не получается?
@user-nc6gt7gb1x
@user-nc6gt7gb1x Год назад
Скажите , как в функцию loadLayoutMiddleware(route) попадет route, мы же const route = useRoute() не делали🤔
@dev-workshop
@dev-workshop Год назад
Так работают мидлварки, роутер сам передает роут в каждую мидлварку и ожидает каких-то манипуляций с ним и вызывает мидлварки по цепочке :) А еще функция useRoute может быть вызвана только топ левел в файлах компонентов
@user-nc6gt7gb1x
@user-nc6gt7gb1x Год назад
@@dev-workshop Спасибо! :)
@dev-workshop
@dev-workshop Год назад
@@user-nc6gt7gb1x Пожалуйста :)
@grantorino3465
@grantorino3465 Год назад
а почему в последнем подходе сперва маунтится шаблон страницы, а потом после него шаблон леяута, если страница - это дочерний компонент леяута?
@dev-workshop
@dev-workshop Год назад
Потому что сначала маунтятся самые глубокие дети и потом всплывает наверх) medium.com/@brockreece/vue-parent-and-child-lifecycle-hooks-5d6236bd561f
@user-vb6xh6yj4h
@user-vb6xh6yj4h 2 года назад
Привет, Объясни пожалуйста, почему дефолтный метод обработки лайоутов через vue-router не подходит?
@dev-workshop
@dev-workshop 2 года назад
Привет! А что ты подразумеваешь под дефолтным?
@user-vb6xh6yj4h
@user-vb6xh6yj4h 2 года назад
@@dev-workshop когда в роутах указываешь лейоут и его childrens; ``` { path: "/", name: "ALayout", component: () => import("../layouts/A/index.vue"), children: [ { path: "/one", name: "OnePage", component: () => import(../views/OnePage.vue"), }, { path: "/two", name: "OnePage", component: () => import(../views/TwoPage.vue"), }, ] }, { path: "/", name: "BLayout", component: () => import("../layouts/B/index.vue"), children: [ { path: "/three", name: "ThreePage", component: () => import(../views/ThreePage.vue"), }, { path: "/four", name: "FourPage", component: () => import(../views/FourPage.vue"), }, ] } ```
@dev-workshop
@dev-workshop 2 года назад
@@user-vb6xh6yj4h В первые сталкиваюсь с таким подходом, если честно :) Так как я с ним не работал могу только поверхностно его проанализировать. Во-первых на мой взгляд использование дочерних роутов именно для лэйаутов не совсем подходящий инструмент - субъективщина Во-вторых, будет создан два раза роут с путем "/", хотя по идее, его быть не должно, если мы все страницы раскидали. В третьих, у неопытных разработчиков могут возникнуть вопросы относительно того, как именно будет резолвится этот несчастный роут "/" В четвертых, а как мне разместить страницу с выбранным лэйаутом по пути "/"? В пятых, что делать, если я хочу по роуту "/product/item" иметь лэйаут "main", а по роуту /product/item/actions лэйаут "productActionsLayout"? Ну и тому подобное по вложенным маршрутам с разными лэйаутами. В целом, вышеперечисленное мной - скорее придирки, основанные на поверхностном анализе, нужно смотреть глубже и ковырять. Я еще нашел способ, кажется он еще проще моего, использовать named-view v3.router.vuejs.org/guide/essentials/named-views.html#nested-named-views но вопрос, будет ли корректно работать, если один компонент, будет вложен в другой
@dev-workshop
@dev-workshop 2 года назад
@@user-vb6xh6yj4h В первые сталкиваюсь с таким подходом, если честно :) Так как я с ним не работал могу только поверхностно его проанализировать. Во-первых на мой взгляд использование дочерних роутов именно для лэйаутов не совсем подходящий инструмент - субъективщина Во-вторых, будет создан два раза роут с путем "/", хотя по идее, его быть не должно, если мы все страницы раскидали. В третьих, у неопытных разработчиков могут возникнуть вопросы относительно того, как именно будет резолвится этот несчастный роут "/" В четвертых, а как мне разместить страницу с выбранным лэйаутом по пути "/"? В пятых, что делать, если я хочу по роуту "/product/item" иметь лэйаут "main", а по роуту /product/item/actions лэйаут "productActionsLayout"? Ну и тому подобное по вложенным маршрутам с разными лэйаутами. В целом, вышеперечисленное мной - скорее придирки, основанные на поверхностном анализе, нужно смотреть глубже и ковырять. Я еще нашел способ, кажется он еще проще моего, использовать named-view v3.router.vuejs.org/guide/essentials/named-views.html#nested-named-views но вопрос, будет ли корректно работать, если один компонент, будет вложен в другой
@user-vb6xh6yj4h
@user-vb6xh6yj4h 2 года назад
@@dev-workshop поизучайте подробнее, потом поделитесь, роут выполняет все поставленные требования=))
@johnshvets8593
@johnshvets8593 2 года назад
А что если мы внутри лейаута ходим на сервер и хотим чтоб дочерний компонент не маунтился, пока он туда не сходит? В таком случае этот подход не совсем работает или я ошибаюсь?
@dev-workshop
@dev-workshop 2 года назад
Я думаю, что подходит, как раз таки потому, что маунт лэйаута, при таком подходе вызовется один раз. Точно сработает если ходить на сервер будет AppLayoutDefault или AppLayoutLogin А вообще, я делаю все запросы на сервер, которые "общие" в отдельной мидлварке, ее можно сделать блокирующей рендер или не блокирующей
@xeleos
@xeleos Год назад
@@dev-workshop на тему общих запросов в мидлварке было бы классно видео от вас увидеть, если там есть что рассказать
@dev-workshop
@dev-workshop Год назад
@@xeleos Привет!) А что подразумевается под общими запросами?
@wwiiktor
@wwiiktor Год назад
@@dev-workshop вы же сами комментарием выше упомянули об этом. На самом деле осведомлённость документацией у вас хорошая , лично я, благодаря вам узнал о возможности их(мидлвар.) использовать в принципе. Благодарю за ликбез.
@dev-workshop
@dev-workshop Год назад
@@wwiiktor Очень рад!) Да иногда забываю о чем были комментарии в ранних видео. Если речь про запросы, которые общие для всех страниц (пользователь, пермишены, общая инфа и тд), то в принципе, можно записать видос, конечно)
@mikhailwalle9556
@mikhailwalle9556 Год назад
Привет! Пытаюсь применить указанный 3-ий способ с воем проекте. Тут TS ругается на "route.meta.layoutComponent": Type VueElement | undefined is not assignable to type string | ComponentDefinition Буду благодарен за комментарий.)
@dev-workshop
@dev-workshop Год назад
Привет! А ты не забыл? declare module "vue-router" { interface RouteMeta { layout?: AppLayoutsEnum; layoutComponent?: VueElement; } }
@HalauLilau
@HalauLilau 10 месяцев назад
С этим лайоут системой столкнулся на такое когда меняется хэш (window.location.hash) загружает снова лейоут и страница фризится
@dev-workshop
@dev-workshop 10 месяцев назад
Надо смотреть, что в этот момент происходит с роутером вьюшным
@HalauLilau
@HalauLilau 10 месяцев назад
@@dev-workshop Страница состоит из двух блоков ЛЕВАЯ часть просто список линков по клику вызывается функция которая ищет в DOM element(ПРАВАЯ часть) если находит делает scroll ПРАВУЮ часть и потом добавляет в адрес localtion.hash = '#somehash' (пробывал и $router.push({hash:''})
@HalauLilau
@HalauLilau Год назад
Есть лайот шапка внутри инпут с выпадающию меню и у каждой страницы выпадающию меню свой. Как реализовать такое отношение?
@dev-workshop
@dev-workshop Год назад
либо через внешний стор, либо сделать композабл с замыканием состояния и на каждой странице обновлять данные для выпадашки
@HalauLilau
@HalauLilau Год назад
@@dev-workshop замыкание состояние страницы?
@dev-workshop
@dev-workshop Год назад
​@@HalauLilau нет, пишешь замыкание внутри которого используешь, грубый пример const dropdownData = useRef(); export function useLayoutDropdown() { function updateData(newValue) { dropdownData.value = newValue; } return reactive( { dropdownData, updateData }) } затем в лейауте вызываешь useLayoutDropdown и используешь из него данные и на страницы используешь useLayoutDropdown и обновляешь данные. Но это очень грубый пример, здесь получается синглтон, который нельзя использовать, если у тебя ssr Но никто не мешает создать такое замыкание в контексте запроса
@dev-workshop
@dev-workshop Год назад
@@HalauLilau еще можно рулить данными для выпадашки на уровне роутера
@HalauLilau
@HalauLilau Год назад
@@dev-workshop у меня ssr нет. Оказывается не только данные и иинпуты и селекты разные. Например страница клиент там в дропдауне фильтр поле дата, город, номер. А проектах другие поля в дродауне
@user-hruser
@user-hruser 3 дня назад
на сколько обоснован динамичесикй импорт? прочему не обычный?
@dev-workshop
@dev-workshop 3 дня назад
на столько же, на сколько обоснован code splitting
@mnemo-tech
@mnemo-tech Год назад
Почему не использовать двухуровневый router? Два RouterVue, один для layout-ов, второй для page-ов. И все ... никаких лишних маунтов. Просто надо настроить правильно роутер...
@dev-workshop
@dev-workshop Год назад
Не рассматривал такой вариант. Надо подумать
@a_mensky
@a_mensky Год назад
Согласен, я использую двyxypoвнeвый роутер. В шаблоне layout компонентов достаточно добавить router-view в нужное место и сделать сборщик роутинга. Минус подхода: - Нужны префиксы в урлах, типо /panel /login либо смириться что на корневой url будет 1 layout - Нужно один раз написать инфраструктурный код который будет собирать роутинг и класть страницу в childs с нужным layout. Плюсы: - Так как страницы префиксные, легко добавить глобальный permissions guards по типу user должен быть авторизован. - Не нужно в описаниях новых страниц тащить импорты на layout - Нет middleware’s - Динамический импорт работают нативно через функцию в качестве параметра component. - Можно натравить webpack чтобы он собирал несколько страниц в один chunk - Конфиг страницы прост до ужаса, url, component, meta в котором прописано название layout
@dev-workshop
@dev-workshop Год назад
@@a_mensky а можешь скинуть минимальную демку?
@a_mensky
@a_mensky Год назад
@@dev-workshop ссылку постил, куда то пропадает
@Atelier155
@Atelier155 Год назад
@@a_mensky привет, а можешь в телегу скинуть где почитать об этом методе? flexsoxo
@adms_dev
@adms_dev Год назад
С компютедом работает, причем все правильно, я буквально немного переписал и все отрабатывает как должно быть, вот лог из консоли, сначала зашел на дефолтную страницу с дефолт лейаутом и потом перешел на другую страницу с другим лейаутом. Если что версия vue - 2. LOG: HomeView has been mounted DefaultLayout has been mounted DefaultLayout has been destroyed HomeView has been destroyed ErrorView has been mounted ErrorLayout has been mounted
@dev-workshop
@dev-workshop Год назад
Да, на 2 вью работает, я согласен. На 3 начинаются пляски :) А что именно ты переписал?
@hellocsgo3600
@hellocsgo3600 Год назад
красавчик / как раз увидел эту проблему двойного рендера при переключении лэйаута и искал решение
@dev-workshop
@dev-workshop Год назад
Спасибо) Рад, что твоя проблема решена :)
@hellocsgo3600
@hellocsgo3600 Год назад
@@dev-workshop спасибо 👍
@hellocsgo3600
@hellocsgo3600 Год назад
@@dev-workshop если не сложно подскажите пожалуйста, для работы с данными , например юзер залогинился, использовать vuex ?
@dev-workshop
@dev-workshop Год назад
@@hellocsgo3600 Если мы говорим про 3 вью - то лучше pinia. Но можно жить вообще без state manager'a
@hellocsgo3600
@hellocsgo3600 Год назад
@@dev-workshop я vue 3 учу, спасибо посмотрю pina
@TheHaykokalipsis
@TheHaykokalipsis Год назад
Привет. Я нашёл баг который не смог сам исправить и запостил его тебе на гитлаб репо этого проекта. Посмотри пожалуйста.
@dev-workshop
@dev-workshop Год назад
Привет! Хорошо, гляну. Спасибо!
@dev-workshop
@dev-workshop Год назад
Это не баг, это желание использовать данный механизм иначе. В твоем случае стоит сделать несколько иначе, я отписал там в ишью
@evgeniynone5760
@evgeniynone5760 2 года назад
А в чём суть канала ? Разбор решений ?
@dev-workshop
@dev-workshop 2 года назад
Суть канала, на текущий момент - поделиться некоторым опытом в веб разработке, показать решение некоторых проблем. Продемонстрировать альтернативные подходы к решению задач. Когда я сталкиваюсь с какими-либо проблемами в разработке или нахожу их в чужих проектах, иногда я придумываю оригинальные (на мой взгляд) решения и делюсь этими решениями. Возможно, суть канала изменится со временем, хочется делать информативный контент для разработчиков
@Yarkendar
@Yarkendar Год назад
Как-то сложно Использую children-компонент в роутере { path: "/users", name: "usersLayout", component: MainLayout, children: [ { path: "", name: "users", component: UsersPage, }, ], }, Здесь MainLayout это основной шаблон, usersLayout просто название роута
@dev-workshop
@dev-workshop Год назад
На вкус и цвет. Сейчас не могу точно сказать, но по-моему у такого варианта есть проблемы с асинхронными импортами и как следствие - код сплиттингом, но могу ошибаться. Ну и да, на вкус и цвет, как говориться ИМХО: разве это проще? Как конечный разработчик, который будет переодически добавлять новые роуты, мне не очень нравится описание роута. свойство children описывает вложенные роуты. В Вашем примере, почти всегда будет вложенный роут "по-умолчанию". А является ли он действительно вложенным, или он нужен только для реализации лэйаута? А что с дефолтным лейаутом? А будет ли ререндериться "MainLayout" при переходе между Роутами первого уровня? А нужно ли разработчику думать в чем разница между $router.push({name: "users"}) и $router.push({name: "usersLayout"}) ? Выполнив $router.push({name: "usersLayout"}) какое имя будет у конечного роута? произойдет ли автоматический переход на роут с именем "users"? будут ли существовать два роута с разными именами но с одинаковым отображением? Все эти вопросы возникают у меня, глядя на Ваш пример. При этом я не помню ответы на них, мне нужно идти и проверять. Ну и кажется Вы упустили тот момент, что я делал решение, которое близко по АПИ к наксту, о чем я говорил в начале видео
Далее
Vue3 крутейший лоадер/спиннер
13:41
Все мы немного Адриана 😂😂😂
00:11
МОЩЩЩНОСТЬ ZEEKR 001 FR
00:46
Просмотров 696 тыс.
REALLY LOVES CHIPS
00:19
Просмотров 2,3 млн
Vue.js Modular Architecture
11:48
Просмотров 46 тыс.
🐞🔍 VUE 3 hacks to improve debug
4:13
Просмотров 1,1 тыс.
Drag and Drop на Vue 3 / Уроки Vue
15:23
Просмотров 20 тыс.