В Vue и Vue Router SPA, показывая 404 для не найденного ресурса
Я использую Vue и Vue Router в SPA. В компоненте представления я запрашиваю репозиторий для ресурса. Если ресурс не найден, я хочу показать страницу 404 с сохранением URL.
Т.е. если я приеду /foo/non-existant-id
тогда страница 404 должна отображаться вместо страницы показа для foo
ресурс.
Для наглядности вот моя карта роутера:
router.map({
'/foo/:id': {name: 'foo-show', component: FooShowPage},
// Utilities
'/': { name: 'home', component: HomePage },
'*': { name: '404', component: NotFoundPage }
})
И по моему FooShowPage
Я делаю следующее:
ready () {
// fetch the foo from the repo (app.foos)
app.foos.fetchById(this.$route.params.id).then(foo => {
this.foo = foo
}).catch(e => {
// foo is not found show a 404 page
// using this.$route.router.go({name: '404'}) does not work as route is a wildcard
console.warn(e)
})
}
По сути, это, вероятно, будет связано с заменой FooShowPage
в представлении роутера с NotFoundPage
или перенаправить на определенную страницу 404, не затрагивая историю браузера.
2 ответа
Вам необходимо установить маршрут для страницы 404, а затем перенаправить на него несопоставленные маршруты. Я использую router.redirect
после карты делать такие вещи.
router.map({
'/': { name: 'home', component: HomePage },
'/foo/:id': {name: 'foo-show', component: FooShowPage},
'/404': {name: 'not-found', component: NotFound}
})
router.redirect({
'*': '/404'
})
Все маршруты, которые НЕ перечислены на карте, будут перенаправлены на /404
Нашел решение на форуме Vue.js - используйте навигационную защиту:
import store from '../store'
{
path: '/lavori/:lavoro',
name: 'lavoro',
component: Lavoro,
beforeEnter: (to, from, next) => {
function isValid (id) {
return store.getters.resourceByID(id) !== undefined
}
if (!isValid(to.params.id)) {
next({ name: 'not-found' });
}
next();
}
},
Edit1: необходимо import store
чтобы получить доступ к геттерам, из этой проблемы Github и этого вопроса
Еще вопрос, как оставить такой же (запрошенный) URL
Лучшее, что я понял, - это использование глобального перехватчика с Axios для перенаправления всех 404 ответов, полученных через API, на маршрут 404. Однако это меняет URL на /404, как ответ @Leo.
const http = axios.create({
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
// Add some global response intercepters
http.interceptors.response.use(function (response) {
// For successes just continue as normal
return response;
}, function (error) {
// If we have a 404 redirect to the error page replacing the history
if (error.response.status === 404) {
return router.replace({ name: 'notfound' });
}
return Promise.reject(error);
});
export default http;