Как насчёт динамического меню когда глубина вложенности неизвестна? Пример из жизни — сайдбар. Под катом реализация для React и Vue.
В качестве мока используем данные из trees.js
.
// tree.js
const tree = [
{ name: 'Level 1.1' },
{
name: 'Level 1.2',
children: [
{ name: 'Level 2.1' },
{ name: 'Level 2.2' }
]
},
{
name: 'Level 1.3',
children: [
{ name: 'Level 2.3' },
{ name: 'Level 2.4' },
{
name: 'Level 2.5',
children: [
{ name: 'Level 3.1' },
{
name: 'Level 3.2',
children: [
{ name: 'Level 4.1' },
{ name: 'Level 4.2' }
]
},
{ name: 'Level 3.3' }
]
}
]
}
]
export default tree
React
Создать новый проект.
$ npx create-react-app new-project
$ cd new-project
$ npm run start
Структура проекта:
.
├── src
│ ├── App.js
│ ├── components
│ │ ├── Sidebar.js
│ │ └── SidebarItem.js
│ ├── index.js
│ └── tree.js
└── public
Точка входа. Здесь будеть жить сайдбар и функция handleClick
,
которая сможет принять данные при клике на любой элемент из списка.
import React from 'react'
import tree from './tree'
import Sidebar from './components/Sidebar'
function handleClick (e) {
e.preventDefault();
// При клике на любой пункт вывести название пункта
console.log(e.target.textContent)
}
export default function App() {
return <Sidebar items={tree} handleClick={handleClick} />
}
Vue
Vue отличается от React своей магией. Не всегда очевидно то, что фреймворк хранит «под капотом», но порой эта магия может упростить жизнь. Но не в этом случае. Логика аналогична той, что мы писали выше.
Создадим новый проект. Для простоты сделаем это с vue-cli.
$ npx @vue/cli create new-project
$ cd new-project
$ npm run serve
Структура проекта:
.
├── public
└── src
├── App.vue
├── components
│ ├── Sidebar.vue
│ └── SidebarItem.vue
├── main.js
└── tree.js
Точка входа. Подключим компоненты и прокинем данные.
<template>
<div id="app">
<sidebar :data="tree" @handleClick="handleClick" />
</div>
</template>
<script>
import tree from './tree'
import Sidebar from './components/Sidebar'
export default {
name: 'app',
data () {
return {
tree
}
},
components: {
Sidebar
},
methods: {
handleClick (node) {
console.log('Clicked: ', node.name)
}
}
}
</script>