В 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;
Другие вопросы по тегам