Мета-поля маршрутизатора Vue

#typescript #vue.js #vue-router

#typescript #vue.js #vue-маршрутизатор

Вопрос:

Мне было интересно, возможно ли определять пользовательские свойства при передаче маршрутов в VueRouter. Например, для большинства маршрутов в моем приложении я хотел бы определить маршрут, подобный следующему, где я могу передать компонент в необязательное свойство «menu»:

 { path: "/section-stack", component: SectionStack, menu: SectionMenu }
  

Чтение документов указывает на использование мета-поля для этого, но это не достигает того, чего я хочу, и приводит к более подробным маршрутам. Если посмотреть на код, то каждый маршрут, передаваемый VueRouter, имеет тип RouteConfig. Можно ли модифицировать мой VueRouter так, чтобы ему можно было передавать маршруты другого типа? Т.е. типа RouteConfig с дополнительными свойствами.

Ответ №1:

Я думаю, meta что это все еще правильный путь. Однажды я создал с его помощью breadcrumb. Мой маршрут выглядел следующим образом:

   routes: [
    {
      path: '/',
      name: 'home',
      component: require('./routes/Home.vue'),
      meta: {
        history: [],
      },
    },
    {
      path: '/projects',
      name: 'projects',
      component: () => System.import('./routes/Projects.vue'),
      meta: {
        history: ['home'],
      },
    },
    {
      path: '/project/:token',
      name: 'project',
      component: () => System.import('./routes/project/Overview.vue'),
      meta: {
        text: (vue) => vue.projects[vue.$route.params.token] || vue.$route.params.token,
        to: { name: 'project', params: { token: (vue) => vue.$route.params.token } } ,
        history: ['home', 'projects'],
    }
  ]
  

В моем vue-компоненте я мог получить доступ к мета-данным, просматривая $route и загружая компонент, выполняя итерации по $router объекту следующим образом:

 export default {
    beforeMount() {
      this.allRoutes = {};
      this.$router.options.routes.forEach(route => {
          if (route.name) {
            let text = (route.meta amp;amp; route.meta.text) || route.name;
            this.$set(this.allRoutes, route.name, {
                text: text,
                to: (route.meta amp;amp; route.meta.to) || { name: route.name }
              }
            );
          }
        }
      );
    },
    data() {
      return {
        allRoutes: {},
        currentList: [],
      };
    },
    watch: {
      '$route'(to, from) {
        this.currentList = ((to.meta amp;amp; to.meta.history).slice(0) || []);
        this.currentList.push(to.name);
      }
    },
  }
  

В частности, forEach in beforeMount может быть решением для создания меню, которое, например, основано на ролях, определенных в мета-объекте.

Комментарии:

1. Спасибо за ваш ответ. Я поддержал вас, но не принял ваш ответ, поскольку это не то, что я ищу. Еще одна причина, по которой я хотел бы использовать конкретное свойство компонента type, заключается в том, что оно было бы типобезопасным, если as meta принимает любой тип.

2. Если вы хотите meta обеспечить типобезопасность в своем приложении, вы могли бы определить настраиваемый для конкретного приложения, RouteConfig который определяет определенный тип для ваших полей, которые вы хотите определить в meta свойстве. Например: импортируйте { RouteConfig } из ‘vue-router’ … тип экспорта MyAppRouteConfig = Опустить<RouteConfig, ‘meta’> amp; { meta: { свойство1: строка, свойство2: число, … } } Недостатком этого является то, что вам приходится ссылаться на этот тип во всем вашем приложении, а не импортировать его RouteConfig из vue-router напрямую, извините, форматирование испорчено

Ответ №2:

Чтобы дополнить мой комментарий в первом ответе (форматирование не поддерживается в комментариях) и отталкиваться от ответа Маркуса Мадеи, если вы хотите, чтобы meta свойство было типобезопасным, вы могли бы определить свой собственный пользовательский тип, расширяющий RouteConfig :

 import { RouteConfig } from 'vue-router'
...
export type MyAppRouteConfig = Omit<RouteConfig, 'meta'> amp; {
  meta: {
    property1: string,
    property2: number,
    ...
  }
}