Maison  >  Article  >  interface Web  >  Comment implémenter un menu arborescent pliable dans Vue.js

Comment implémenter un menu arborescent pliable dans Vue.js

亚连
亚连original
2018-06-15 16:42:164526parcourir

Dans cet article, je vais vous montrer comment utiliser efficacement les composants récursifs. Je procéderai étape par étape en créant un menu arborescent extensible/réduit. A travers cet article, je vais partager avec vous comment implémenter un menu arborescent pliable à l'aide des composants récursifs de Vue.js. Les amis qui en ont besoin peuvent s'y référer

Appel d'un composant récursif. dans Vue.js est lui-même, tel que :

Vue.component('recursive-component', {
  template: `<!--Invoking myself!-->
       <recursive-component></recursive-component>`
 });

Les composants récursifs sont souvent utilisés pour afficher des commentaires sur des blogs, des menus imbriqués ou fondamentalement le même type de parent et d'enfant, bien que le contenu spécifique soit différent. Par exemple :

Maintenant, pour vous montrer comment utiliser efficacement les composants récursifs, je vais procéder étape par étape en créant un menu arborescent extensible/réduit.

Structures de données

Un composant récursif d'une interface utilisateur arborescente sera une représentation visuelle d'une structure de données récursive. Dans ce tutoriel, nous utiliserons une structure arborescente, où chaque nœud est un objet :

une propriété label.

Si elle a des nœuds enfants, une propriété de nœuds est une propriété de tableau d'un ou plusieurs nœuds.

Comme toutes les structures arborescentes, elle doit avoir un nœud racine, mais peut être infiniment profonde.

let tree = {
  label: &#39;root&#39;,
  nodes: [
   {
    label: &#39;item1&#39;,
    nodes: [
     {
      label: &#39;item1.1&#39;
     },
     {
      label: &#39;item1.2&#39;,
      nodes: [
       {
        label: &#39;item1.2.1&#39;
       }
      ]
     }
    ]
   }, 
   {
    label: &#39;item2&#39; 
   }
  ]
 }

Composant récursif

Créons un composant récursif pour afficher notre structure de données appelé TreeMenu. Il affiche uniquement l'étiquette du nœud actuel et s'appelle pour afficher tous les nœuds enfants. Nom du fichier : TreeMenu.vue, le contenu est le suivant :

<template>
  <p class="tree-menu">
   <p>{{ label }}</p>
   <tree-menu 
    v-for="node in nodes" 
    :nodes="node.nodes" 
    :label="node.label"
   >
   </tree-menu>
  </p>
 </template>
 <script>
  export default { 
   props: [ &#39;label&#39;, &#39;nodes&#39; ],
   name: &#39;tree-menu&#39;
  }
 </script>

Si vous utilisez un composant de manière récursive, vous devez d'abord faire une définition globale pour Vue.component, ou lui donner un attribut de nom. Sinon, aucun composant enfant ne pourra l'appeler davantage et vous obtiendrez un message d'erreur non défini "Erreur de composant non défini".

Événements de base

Comme pour toute fonction récursive, vous avez besoin d'un événement de base pour mettre fin à la récursion, sinon le rendu continuera indéfiniment. finalement conduire à un débordement de pile.

Dans le menu arborescent, nous souhaitons arrêter la récursion lorsque nous atteignons un nœud qui n'a pas d'enfant. Vous pouvez le faire via v-if , mais notre choix d'utiliser v-for l'implémentera implicitement pour nous ; si le tableau de nœuds n'a pas d'autres définitions, le composant arborescence sera appelé. Le fichier template.vue est le suivant :

<template>
  <p class="tree-menu">
   ...
   <!--If `nodes` is undefined this will not render-->
   <tree-menu v-for="node in nodes"></tree-menu>
 </template>

Utilisation

Comment utilisons-nous ce composant maintenant ? Tout d'abord, nous déclarons une instance Vue avec une structure de données comprenant un attribut de données et un composant treemenu défini. Le fichier app.js ressemble à ceci :

import TreeMenu from &#39;./TreeMenu.vue&#39;
 let tree = {
  ...
 }
 new Vue({
  el: &#39;#app&#39;,
  data: {
   tree
  },
  components: {
   TreeMenu
  }
 })

N'oubliez pas que notre structure de données a un nœud racine. Nous commençons à appeler récursivement le composant TreeMenu dans le modèle principal, en utilisant l'attribut root nodes des accessoires :

<p id="app">
  <tree-menu :label="tree.label" :nodes="tree.nodes"></tree-menu>
 </p>

Voici à quoi il ressemble actuellement :

Posture correcte

Il est bon d'identifier visuellement la « profondeur » des sous-composants afin que l'utilisateur puisse avoir une idée de la structure des données de l'interface utilisateur. Réalisons cela en indentant les nœuds enfants à chaque niveau.

Ceci est réalisé en ajoutant une définition d'accessoire de profondeur via TreeMenu. Nous utiliserons cette valeur pour lier dynamiquement les styles en ligne avec les transformations : la règle CSS pour transform : translate sera utilisée pour l'étiquette de chaque nœud, créant ainsi un retrait. template.vue est modifié comme suit** : **

<template>
  <p class="tree-menu">
   <p :style="indent">{{ label }}</p>
   <tree-menu 
    v-for="node in nodes" 
    :nodes="node.nodes" 
    :label="node.label"
    :depth="depth + 1"
   >
   </tree-menu>
  </p>
 </template>
 <script>
  export default { 
   props: [ &#39;label&#39;, &#39;nodes&#39;, &#39;depth&#39; ],
   name: &#39;tree-menu&#39;,
   computed: {
    indent() {
     return { transform: `translate(${this.depth * 50}px)` }
    }
   }
  }
 </script>

L'attribut de profondeur commence à zéro dans le modèle principal. Dans le modèle de composant ci-dessus, vous pouvez voir que cette valeur est incrémentée chaque fois qu'elle est transmise à un nœud enfant.

<p id="app">
  <tree-menu 
   :label="tree.label" 
   :nodes="tree.nodes"
   :depth="0"
  ></tree-menu>
 </p>

REMARQUE : N'oubliez pas de lier en V la valeur de profondeur pour vous assurer qu'il s'agit d'un type de nombre JavaScript et non d'une chaîne.

Développer/Réduire

Étant donné que les structures de données récursives peuvent être volumineuses, c'est une bonne solution pour leur montrer l'astuce de l'interface utilisateur consiste à masquer tous les nœuds à l'exception du nœud racine afin que l'utilisateur puisse développer ou réduire les nœuds selon ses besoins.

Pour ce faire, nous ajouterons un salon immobilier localEnfants . Si sa valeur est False, le nœud enfant ne sera pas rendu. Cette valeur doit être basculée en cliquant sur le nœud, nous devons donc utiliser une méthode d'écoute d'événement de clic toggleChildren pour la gérer. Le fichier template.vue est modifié comme suit** : **

<template>
  <p class="tree-menu">
   <p :style="indent" @click="toggleChildren">{{ label }}</p>
   <tree-menu 
    v-if="showChildren"
    v-for="node in nodes" 
    :nodes="node.nodes" 
    :label="node.label"
    :depth="depth + 1"
   >
   </tree-menu>
  </p>
 </template>
 <script>
  export default { 
   props: [ &#39;label&#39;, &#39;nodes&#39;, &#39;depth&#39; ],
   data() {
    return { showChildren: false }
   },
   name: &#39;tree-menu&#39;,
   computed: {
    indent() {
     return { transform: `translate(${this.depth * 50}px)` }
    }
   },
   methods: {
    toggleChildren() {
     this.showChildren = !this.showChildren;
    }
   }
  }
 </script>

Résumé

De cette façon, nous avons un menu arborescent. Comme touche finale, vous pouvez ajouter une icône plus/moins pour rendre l'interface utilisateur plus visible. J'ai également ajouté d'excellentes capacités de police et de calcul au showChildren original.

Allez sur CodePen (https://codepen.io/anthonygore/pen/PJKNqa) pour voir comment je l'ai implémenté.

J'ai compilé ce qui précède pour vous, j'espère que cela vous sera utile à l'avenir.

Articles connexes :

Implémentation de plusieurs implémentations de routage dans Vue-Router2.X

Interprétation détaillée des composants contrôlés par réaction et non contrôlés composants

Utilisation des fonctions de routage et de hook dans Vue2 >

Utilisez le plug-in de chargement différé d'image dans vue-lazyload

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn