2017-12-20 1 views
0

Dieses Grabbing ist das, was ich in index.php haben, eine side-nav KomponenteMakeln Klassen mit Vue Js, alle Requisiten aus der Komponente

<div class="container"> 
    <side-nav></side-nav> 
</div> 

Dies ist, was ich in SideNav.vue haben

<template> 
<div class="container"> 
    <nav-section name="General"> 
     <nav-item name="Home"> 
      <nav-child name="Dahsboard 1" url="#"></nav-child> 
      <nav-child name="Dahsboard 2" url="#"></nav-child> 
     </nav-item> 

     <nav-item name="Settings"> 
      <nav-child name="Setting 1" url="#"></nav-child> 
      <nav-child name="Setting 2" url="#"></nav-child> 
     </nav-item> 

     <nav-item name="Admin"> 
      <nav-child name="Admin 1" url="#"></nav-child> 
      <nav-child name="Admin 2" url="#"></nav-child> 
     </nav-item> 
    </nav-section> 

    <nav-section name="Data Analysis"> 
     <nav-item name="Data Source"> 
      <nav-child name="Source 1" url="#"></nav-child> 
      <nav-child name="Source 2" url="#"></nav-child> 
     </nav-item> 

     <nav-item name="Visualization"> 
      <nav-child name="Chart 1" url="#"></nav-child> 
      <nav-child name="Chart 2" url="#"></nav-child> 
     </nav-item> 

     <nav-item name="Others"> 
      <nav-child name="Other 1" url="#"></nav-child> 
      <nav-child name="Other 2" url="#"></nav-child> 
     </nav-item> 
    </nav-section> 
</div> 
</template> 

<script> 
    import NavSection from './NavSection.vue' 
    import NavItem from './NavItem.vue' 
    import NavChild from './NavChild.vue' 

    export default { 
     components: { 
      'nav-section':NavSection, 
      'nav-item': NavItem, 
      'nav-child': NavChild, 
     }, 

     data() { 
      return { 

      } 
     }, 

     mounted() { 
      console.log('Component mounted.') 
     }, 


    } 
</script> 

Dies ist, was ich in NavSection.vue haben

<template> 
    <section> 
     <h6>{{ name }}</h6> 

     <ul> 
      <slot></slot> 
     </ul> 
    </section> 
</template> 

<script> 
    export default { 
     props: ['name'], 

     data() { 
      return { 

      } 
     } 
    } 

</script> 

Dies ist, was ich in NavItem.vue haben

<template> 
    <li> 
     <a @click="toggleClass">{{ name }}</a> 

     <ul :class="{ 'active': isActive}"> 
      <slot></slot> 
     </ul> 
    </li> 
</template> 

<script> 
    export default { 
     props: ['name'], 

     data() { 
      return { 
       isActive: false, 
       names: [] 
      } 
     }, 

     created() { 
      //this returns all the names in console 
      console.log(this.name) 

      //However, saving it to data->names array, only saves the clicked item 
      this.names = this.name 
     }, 

     methods: { 

      toggleClass() { 
       this.isActive = true 

       //this works, but I want the value to go back to FALSE once I clicked on another item 

       //one way I think it can be accomplished is comparing the cliked item's name prop with all the names 
       //something like this, (refer to created method) 
       this.names.forEach(element => { 
        this.isActive = (element.name == this.names) 
       }) 

      } 
     } 

    } 
</script> 

Und das ist, was ich in NavChild.vue haben

<template> 
    <li> 
     <a :href="url">{{ name }}</a> 
    </li> 
</template> 

<script> 
    export default { 
     props: ['name', 'url'], 

     data() { 
      return { 

      } 
     } 
    } 
</script> 

Wie Sie sehen können, jeder navSection mehrere navItem hat und jeder navItem hat mehrere navChild Komponenten. Wenn die Funktion toggleClass ausgelöst durch Klicken auf jedes Anker-Tag in der NavItem, möchte ich 1. die isActive Eigenschaft sollte seinen Wert auf TRUE für diesen bestimmten Artikel und 2. isActive geht zurück auf False, sobald ich auf ein anderes Element in jedem Abschnitt klicken .

Ich hatte eine Idee, die funktionieren könnte, wie in der NavItem.vue Datei kommentiert, aber leider could't ich einen Weg, um all die props, sagt name Stütze, für jedes Element aus der NavItem Komponente greifen finden. Gibt es eine Möglichkeit, alle übergebenen Daten für eine bestimmte prop zu greifen und zu speichern?

Jeder Vorschlag zur Verbesserung des Codes oder eine andere bequeme Möglichkeit, um das gleiche Zeug zu erreichen, würde sehr geschätzt werden. Glückliche Kodierung!

+0

Sie verwenden Slots, die als untergeordnete Komponenten nicht gleich sind. Das Funkgruppenverhalten erfordert eine Koordination zwischen den NavItems und ihrer NavSection, was umständlich ist, wenn sie nicht als Eltern/Kind eingerichtet sind. –

+0

ein einfaches Beispiel, um das gleiche zu erreichen, ohne den Slot zu benutzen? Ich habe Slots benutzt, weil es sehr lesbar und sauber ist, wenn es darum geht, ein neues Element im Nav-Bereich hinzuzufügen. Aber ich wäre in Ordnung mit jedem anderen ordentlichen Ansatz @RoyJ – satancorpse

Antwort

2

Sie sind hier in Ihrem Ansatz HTML-orientiert und der Vue-Ansatz soll modellorientiert sein. Anstatt also Ihre Modellstruktur im HTML-Code festzulegen, sollten Sie ein Datenmodell mit der gewünschten Hierarchie erstellen und von Ihren Komponenten rendern lassen.

Ich habe meine App die Sektionsebene gemacht, da Sie sich Sorgen machen, was unterhalb dieser Ebene passiert. Ich habe ein Datenmodell wie im ersten Abschnitt Ihres Beispiels erstellt.

Der Trick bei der Auswahl nur eines Verhaltens besteht darin, dass eine Variable den aktuell ausgewählten Wert enthalten soll. Dieser Wert gehört dem übergeordneten Element. Jedes Kind bekommt eine Requisite, die ihm sagt, ob es der ausgewählte Wert ist.

Wenn ein Kind ausgewählt wird, gibt es ein Ereignis aus, das vom Elternprozess verarbeitet wird (dies ist the Vue way of child-to-parent communication).

Vue.component('nav-child', { 
 
    template: '#nav-child-template', 
 
    props: ['name', 'url'] 
 
}); 
 

 
Vue.component('nav-item', { 
 
    template: '#nav-item-template', 
 
    props: ['name', 'children', 'isActive'], 
 
    methods: { 
 
    toggleClass() { 
 
     this.$emit('activate', this.isActive ? null : this.name); 
 
    } 
 
    } 
 
}); 
 

 
new Vue({ 
 
    el: '#nav-section', 
 
    data: { 
 
    activeItem: null, 
 
    items: [{ 
 
     name: 'Home', 
 
     children: [{ 
 
      name: 'Dashboard 1', 
 
      url: '#' 
 
      }, 
 
      { 
 
      name: 'Dashboard 2', 
 
      url: '#' 
 
      } 
 
     ] 
 
     }, 
 
     { 
 
     name: 'Settings', 
 
     children: [{ 
 
      name: 'Setting 1', 
 
      url: '#' 
 
      }, 
 
      { 
 
      name: 'Setting 2', 
 
      url: '#' 
 
      } 
 
     ] 
 
     } 
 
    ] 
 
    }, 
 
    methods: { 
 
    activate(name) { 
 
     this.activeItem = name; 
 
    } 
 
    } 
 
});
.active { 
 
    border: thin solid red; 
 
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script> 
 
<template id="nav-child-template"> 
 
    <li> 
 
     <a :href="url">{{ name }}</a> 
 
    </li> 
 
</template> 
 

 
<template id="nav-item-template"> 
 
    <li> 
 
     <a @click="toggleClass">{{ name }}</a> 
 

 
     <ul :class="{ 'active': isActive}"> 
 
      <li is="nav-child" v-for="child in children" :name="child.name" :url="child.url"></li> 
 
     </ul> 
 
    </li> 
 
</template> 
 

 
<ul id="nav-section"> 
 
    <li is="nav-item" v-for="item in items" :name="item.name" :is-active="activeItem === item.name" :children="item.children" @activate="activate"></li> 
 
</ul>

+0

Vielen Dank!Ich begann mit einem ähnlichen Ansatz, bei dem ich statt eines Ereignisses einfach die Namen der Elemente mit denen der ausgewählten verglichen habe. Das einzige Problem besteht darin, dass der Effekt "Elemente umschalten" erreicht wird, der Effekt jedoch deaktiviert wird. Der Grund, warum ich das brauche, ist, dass ich ein Admin-Menü hatte, das ich vor ziemlich langer Zeit entwickelt hatte, und ich verwendete jQuery für das, was buchstäblich 10 Sekunden Job war. Kannst du dir vorstellen, wie ich dasselbe erreichen kann, ohne die Funktion "Selbstumschaltung" zu beeinträchtigen? Es macht mir nichts aus, wenn ich dumm bin. Neuling in Vue. – satancorpse

+1

Sicher, ich habe den Code aktualisiert. Lassen Sie es einfach null anstelle des aktuellen Elements ausgeben, wenn das aktuelle Element bereits aktiv ist. –

+0

Ihre Kommentare lösten die Probleme und bereicherten mein Verständnis. Hoffe jemand findet das auch nützlich :) – satancorpse

Verwandte Themen