Сохранение передаваемых params во vueRouter

135
28 мая 2022, 17:10

Есть динамический роут, который выводит отфильтрованный список товаров, фильтрация происходит в getter во vuex, все бы ничего, но если перезагрузить страницу находясь в этом компоненте список не отобразиться тк параметры для фильтрация из родительского компонента не передались. Пробовал использовать хуки, и keep-alive, не помогло. Подскажите как решить данную проблему или посоветуйте бест практисы в таких случаях.

Answer 1

Используя входные параметры во Vue router, вы можете создать фильтр данных по этим параметрам.

Для этого:

  1. Создаете роуты. Для передачи входных параметров, можете использовать функцию, объект, булевы значения. Обратите внимание, когда используете булево значение как true - route.params будут устанавливаться входными параметрами компонента(это касается только route.params). В примере ниже используется функция, которая позволяет приводить параметры к другим типам, комбинировать статические значения с значениями из маршрута(позволяет использовать как route.params так и route.query.*):

    routes: [
       {
         path: "/",
         component: vcatalog,
       },
       {
         path: "/products/",
         component: vcatalog,
       },
       {
         path: "/products/:brand",
         component: vcatalog,
         props: (route) => ({ // функции генерации входных параметров
           type: route.query.type, 
           brand: route.params.brand,
         }),
       },
     ],
    
  2. Создаете компонент, который используется в роутах, как:

    const vcatalog = Vue.component("vcatalog", {
     store,
     props: ["brand", "type"], // инициируем необходимые параметры
     computed: {
       ...mapGetters(["GET_PRODUCTS", "SORTED_PRODUCT"]),
     },
     template: `<div>
     <p>Входные параметры (props)</p>
     <pre>{{ $props }}</pre>
     <hr>
     <template v-if="brand && type"><ul>
         <li v-for="product in SORTED_PRODUCT(brand,type)"> {{ product.text }} ({{ product.type }}/ {{ product.brand }}) </li>
       </ul>
     </template>
     <template v-else>
       <ul>
         <li v-for="product in GET_PRODUCTS"> {{ product.text }} ({{ product.type }}/ {{ product.brand }}) </li>
       </ul>
     </template>
     </pre>
     </div>`,
     });
    

И на выходе вы получите маршруты, которые будут содержать входные параметры, которые будут внедрены в ваш компонент и доступными для использования их в вашей дальнейшей логике (фильтрация и прочее)

Привожу рабочий пример

const {
  mapGetters
} = Vuex;
const store = new Vuex.Store({
  state: {
    products: [{
        id: 1,
        text: "Продукт 1",
        type: "type1",
        brand: "brand1"
      },
      {
        id: 2,
        text: "Продукт 2",
        type: "type2",
        brand: "brand2"
      },
      {
        id: 3,
        text: "Продукт 3",
        type: "type1",
        brand: "brand2"
      },
      {
        id: 4,
        text: "Продукт 4",
        type: "type1",
        brand: "brand1"
      },
      {
        id: 5,
        text: "Продукт 5",
        type: "type2",
        brand: "brand2"
      },
    ],
  },
  getters: {
    GET_PRODUCTS: (state) => (brand) => {
      return brand ? state.products.filter((p) => p.brand === brand) : state.products;
    },
    SORTED_PRODUCT: (state) => (brand, type) => {
      return state.products.filter(
        (p) => p.brand === brand && p.type === type
      );
    },
  },
});
const vcatalog = Vue.component("vcatalog", {
  store,
  props: ["brand", "type"],
  computed: {
    ...mapGetters(["GET_PRODUCTS", "SORTED_PRODUCT"]),
  },
  template: `<div>
    <p>Входные параметры (props)</p>
    <pre>{{ $props }}</pre>
    <hr>
    <template v-if="brand && type"><ul>
        <li v-for="product in SORTED_PRODUCT(brand,type)"> {{ product.text }} ({{ product.type }}/ {{ product.brand }}) </li>
      </ul>
    </template>
    <template v-else>
      <ul>
        <li v-for="product in GET_PRODUCTS(brand)"> {{ product.text }} ({{ product.type }}/ {{ product.brand }}) </li>
      </ul>
    </template>
  </pre>
  </div>`,
});
const router = new VueRouter({
  routes: [{
      path: "/",
      redirect: '/products'
    },
    {
      path: "/products/",
      component: vcatalog,
      name: 'catalog'
    },
    {
      path: "/products/:brand",
      name: 'brand',
      component: vcatalog,
      props: (route) => ({
        type: route.query.type,
        brand: route.params.brand,
      }),
    },
  ],
});
new Vue({
  el: "#app",
  router,
  watch: {
    "$route.fullPath": {
      handler: function(path) {
        this.setNewPath(path);
      },
    },
  },
  created() {
    this.setNewPath();
  },
  methods: {
    goPath() {
      this.$router.push(this.path);
    },
    setNewPath(path) {
      this.path = path || this.$route.fullPath;
    },
  },
});
.router-link-active { color: green }
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/vuex@3.3.0/dist/vuex.js"></script>
<div id="app">
  <router-view></router-view>
  <label for="input">Текущий URL</label>
  <hr>
  <input id="input" v-if="path" type="text" name="path" v-model="path" style="width: 100%; padding: 10px" @keyup.enter="goPath" />
  <p>Тестовые URL</p>
  <ul>
    <li>
      <router-link exact :to="{name: 'catalog'}">/products</router-link>
    </li>
    <li>
      <router-link exact to="/products/brand2?type=type2">/products/brand2?type=type2</router-link>
    </li>
    <li>
      <router-link exact to="/products/brand1?type=type1">/products/brand1?type=type1</router-link>
    </li>
    <li>
      <router-link exact :to="{path: '/products/brand1' }">/products/brand1</router-link>
    </li>
    <li>
      <router-link exact :to="{name: 'brand', params: { brand: 'brand2'} }">/products/brand2</router-link>
    </li>
    <li>
      <router-link exact :to="{name: 'brand', params: { brand: 'brand2'}, query: { type: 'type1' } }">/products/brand2?type=type1</router-link>
    </li>
  </ul>
</div>

READ ALSO
Как вывести ключ и значение TreeMap

Как вывести ключ и значение TreeMap

Если пишем новое имя, программа просит ввести номер телефона и запоминает егоЕсли новый номер телефона — просит ввести имя и также запоминает

158
Передать объект в форме spring

Передать объект в форме spring

Подскажите, как передать объект в форме springЯ использую Thymeleaf

267