#vue.js #vue-router #nested-lists
#vue.js #vue-маршрутизатор #вложенные списки
Вопрос:
Каков подходящий способ достижения вложенных «n» уровней маршрутов на основе выбранной в данный момент категории?
Я хотел бы правильно получить доступ к маршрутам, чтобы мой URL-адрес выглядел следующим образом:
/categories
/categories/outfit/
/categories/outfit/jackets/
/categories/outfit/jackets/mountains/
/categories/outfit/jackets/mountains/you_get_the_idea
У меня есть список категорий, например, так:
const categories = [
{
name: 'outfit',
childs: [
{ name: 'jackets',
childs: [
{ name: 'mountains' }
]
},
{ name: 'pants', childs: ['many subcategories'] },
{ name: 'boots', childs: ['many subcategories'] }
]
},
{
name: 'knives',
childs: [
{ name: 'hunting' },
{ name: 'souvenirs' },
{ name: 'kitchen' },
{ name: 'skinning' },
{ name: 'throwing' }
]
}
]
У меня есть главная страница категорий (ВЕРХНИЙ УРОВЕНЬ):
<div class="col-6" v-for="category in categories" :key="category.id">
<div class="block q-pa-md">
<router-link :to="'/categories/' category.slug">
<h4>{{ category.name }}</h4>
</router-link>
</div>
</div>
И есть вложенная страница для 1-го уровня дочерних элементов:
<h1>{{ category.name }}</h1>
<q-img :src="category.image"/>
<p>{{ category.description }}</p>
<div class="row q-col-gutter-md">
<div class="col-md-4 col-xs-6" v-for="subcategory in category.childs" :key="subcategory.id">
<div class="block q-pa-md">
<router-link :to="'/categories/' subcategory.id">
<h4>{{ subcategory.name }}</h4>
</router-link>
</div>
</div>
</div>
Как бы мне сделать несколько повторяющихся вложенных дочерних элементов?
Комментарии:
1. Я не уверен, правильно ли я понял ваш вопрос. Вы собираетесь иметь определенный маршрут для каждой отдельной страницы, или вам нужны динамические маршруты? Если это так, взгляните на: router.vuejs.org/guide/essentials /…
2. @ThomasBay — У меня есть вложенный набор категорий, где каждая запись содержит дочерние узлы, если другие записи ссылаются на нее как на «parent_id». Для лучшей читаемости URL-адреса я хотел бы сделать URL-адрес вложенным, чтобы пользователь мог глубже проникнуть в дерево категорий
Ответ №1:
Функция динамического сопоставления маршрутов маршрутизатора Vue позволяет определить динамический параметр, который захватывает более одного сегмента пути, определяя ваш маршрут как /categories/:categoryId
(маршрутизатор использует путь к регулярному выражению для сопоставления)
При таком определении route as /categories/outfit/jackets/mountains
будет иметь categoryId
параметр со значением outfit/jackets/mountains
, который можно передать в компонент, легко проанализировать и работать с ним…
Смотрите мой пример ниже:
Vue.config.devtools = false
Vue.config.productionTip = false
const categories = [{
name: 'outfit',
childs: [{
name: 'jackets',
childs: [{
name: 'mountains'
}]
},
{
name: 'pants',
childs: [{
name: 'short'
}, {
name: 'long'
}]
},
{
name: 'boots',
childs: [{
name: 'barefoot'
}, {
name: 'mountains'
}]
}
]
},
{
name: 'knives',
childs: [{
name: 'hunting'
},
{
name: 'souvenirs'
},
{
name: 'kitchen'
},
{
name: 'skinning'
},
{
name: 'throwing'
}
]
}
]
const cat = Vue.component('categories', {
data: function() {
return {
categories: categories // in real life, this data is shared for example using Vuex
}
},
template: `
<div>
<template v-for="cat in categories">
<router-link :to="'/categories/' cat.name" :key="cat.name"> {{ cat.name }} </router-link>
</br>
</template>
</div>
`
})
const catView = Vue.component('category-view', {
data: function() {
return {
categories: categories // in real life, this data is shared for example using Vuex
}
},
props: ['categoryId'],
template: `
<div>
<hr>
<router-link :to="parentCategoryPath"> <- Back </router-link>
<div>Params: {{ categoryId }}</div>
<hr>
<template v-if="categoryDefinition amp;amp; categoryDefinition.childs">
<template v-for="cat in categoryDefinition.childs">
<router-link :to="$route.path '/' cat.name" :key="cat.name"> {{ cat.name }} </router-link>
</br>
</template>
</template>
</div>
`,
computed: {
categoryDefinition() {
let subCategory = this.categories.find(cat => cat.name === this.categoryId[0]);
for (i = 1; i < this.categoryId.length; i ) {
subCategory = subCategory.childs.find(cat => cat.name === this.categoryId[i])
}
return subCategory
},
parentCategoryPath() {
return '/categories/' this.categoryId.slice(0, -1).join('/')
}
}
})
const router = new VueRouter({
base: '/js',
mode: 'history',
routes: [{
path: '/',
redirect: '/categories',
},
{
path: '/categories',
component: cat,
},
{
path: '/categories/:categoryId ',
component: catView,
props: route => ({
categoryId: route.params.categoryId.split('/')
})
}
]
})
const vm = new Vue({
el: '#app',
router,
data: function() {
return {}
}
})
hr {
border: none;
border-top: 3px double #333;
color: #333;
overflow: visible;
text-align: center;
height: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.5.1/vue-router.min.js" integrity="sha512-c5QVsHf336TmWncPySsNK2ncFiVsPEWOiJGDH/Le/5U6q1hU6F5B7ziAgRwCokxjmu4HZBkfWsQg/D/ X3hFww==" crossorigin="anonymous"></script>
<div id="app">
{{ $route.path }}
<router-view></router-view>
</div>
Комментарии:
1. Я использовал ваш подход с немного измененной логикой, и он работает. Спасибо!