Vue-FAQ
919 subscribers
556 photos
90 videos
548 links
Канал сайта https://vue-faq.org
Информация о Vue.js, фронтенд разработке и не только

Contacts: @RuslanMakarov
Download Telegram
Если вы хотите у некоторых страниц сделать свой titlemeta description), то это органично делается через routes и router navigation guard безо всяких useHead-ов

export const routes = [{
name: 'about',
path: '/about',
meta: {
title: 'My name is Bond',
description: 'James Bond',
}
}];


router.beforeEach((to) => {
const { title, description } = to.meta;

document.title = title || 'Default Title';

document
.querySelector('head meta[name="description"]')
.setAttribute('content', description || 'Default Description')
})


#router #tip
Если попытаться использовать vue-router в js/ts модуле или composable функции,

import { useRouter } from "vue-router";

function foo() {
const router = useRouter();
}


то выходит ошибка:

[Vue warn]: inject() can only be used inside setup() or functional components.


Это потому, что vue-router, Pinia, PrimeVue.Toast и многие другие библиотеки используют provide/inject для глобального внедрения своих элементов в ваше приложение.

// vuejs/packages/router/src/useApi.ts

export function useRouter(){
return inject(routerKey)
}


В то же время, provide/inject во Vue работает только в контексте приложения.

Чтобы использовать vue-router в js модулях приходится создавать отдельный синглтон для router, инициализировать его через createRouter() и затем использовать обычный ES импорт где надо. Почему вместо стандартного ES экспорта/импорта сделано такое усложнение через provide/inject не совсем понятно.

Тем не менее, текст вышеуказанной ошибки не совсем корректен, потому что доступ к inject() можно получить явно выполнив код в контексте приложения:

// plugins/debug.ts
import { useRouter } from "vue-router"

export default {
install(app) {
app.runWithContext(() => {
const router = useRouter();
router.addRoute({ "/debug", () => import('@/views/DebugView.vue') });
})
}
}


Это удобно при создании, например, плагинов, когда доступа к своему синглтону router еще нет.

Кстати, на Хабре недавно была большая статья про контексты Vue и Nuxt

#tip #provide #router
Вышел vue-router 4.5.0

Из примечательного - по инициативе Эвана на router-link появился prop view-transition, который задействует нативный View Transitions API для перехода между роутами.

<template>
<RouterLink to="/some-page" view-transition>
Go to some page
</RouterLink>
</template>


Анимацию которого можно кастомизировать CSS стилями

Может быть быстрее вьюшного <Transition> и уж точно удобней в записи (по сравнению с конструкцией с router-view ). Но не такой функциональный, для простых переходов.

#router #animation #css
Если показываете через <router-view> страницу с route параметром (продукты, каталоги, пользователей через id), и надо при смене параметра загружать нового, - то есть, следить за изменением параметра, то делать это можно двумя способами.

Через watch:

watch(
() => props.id,
async () => {
userData.value = await fetchUser(to.params.id);
},
{ immediate: true }
);


Через хук роутера onBeforeRouteUpdate:

js 
import { onBeforeRouteUpdate } from 'vue-router'

onBeforeRouteUpdate(async (to, from) => {
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id);
}
})


Второй способ дает еще возможность использовать onBeforeRouteLeave, если вдруг надо

#router #tip
По большому счету технически SPA - это в основном router

В этой статье показывается пример, как реализовать router на чистом js

С Hash Mode и History Mode

#spa #router
При использовании router-view с transition с mode="out-in" в dev режиме при переходах по роутам часто ловится белый экран

Единственное найденное решение - отключать этот mode в dev режиме

<router-view v-slot="{ Component }">
<Transition mode="out-in">
<component :is="Component" />
</Transition>
</router-view>


#router #tip