Maison > Questions et réponses > le corps du texte
J'utilise nuxt et bootstrap pour créer un menu déroulant de survol personnalisé pour la navigation. Le problème que j'ai est que mon sous-menu de navigation NuxtLinks actualise la page entière au lieu de modifier en douceur le contenu de l'application dans le bloc Nuxt. La barre de navigation est générée dynamiquement dans la mise en page default.vue et utilise le composant b-dropdown-hover avec un NuxtLink encapsulant le contenu. Pourquoi la page est-elle complètement actualisée pour ces liens/ancres, mais mon image de marque b-navbar évolue-t-elle en douceur ? Désolé, je suis nouveau sur Nuxt. Cette vidéo à ~ 1:35:00 montre ce que j'essaie de faire.
components/BDropdownHoverRight.vue
<template> <nuxt-link :to="aTo"> <div class="ddr-top" @mouseover="onOver1($event.target)" @mouseleave="onLeave1($event.target)"> <b-dropdown ref="dropdown_ddr" :text="cText" class="m-md-2 ddr"> <slot></slot> </b-dropdown> </div> </nuxt-link> </template> <script> export default { name: 'BDropdownHoverRight', props: { cText: { type: String, }, aTo: { type: String, }, }, methods: { onOver1(t) { if (t.nodeName === 'DIV') { console.log(t) console.log(t.nodeName) let num_child_nodes = 0 try { if (t.querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length >= 0) { num_child_nodes = t.querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length } } catch (e) { if (t.querySelectorAll(':scope > div > ul')[0].getElementsByTagName('div').length >= 0) { num_child_nodes = t.querySelectorAll(':scope > div > ul')[0].getElementsByTagName('div').length } } if (num_child_nodes > 0) { try { t.querySelectorAll(':scope > div > ul')[0].style.display = 'block' } catch (e) { try { t.querySelectorAll(':scope > ul')[0].style.display = 'block' } catch (e) {} } } } }, onLeave1(t) { try { t.querySelectorAll(':scope > div > ul')[0].style.display = 'none' } catch (e) { try { t.querySelectorAll(':scope > ul')[0].style.display = 'none' } catch (e) {} } }, }, } </script>
layouts/default.vue
<template> <div> <b-navbar id="top-nav-bar" toggleable="lg" type="light" sticky> <b-navbar-brand to="/"> <Rabbit id="tl-logo" /> </b-navbar-brand> <b-navbar-toggle target="nav-collapse"></b-navbar-toggle> <b-collapse id="nav-collapse" is-nav> <b-navbar-nav> <template v-for="dir in navtop_dd"> <b-dropdown-hover :key="dir.id" :c-text="dir.name" :a-to="dir.hasOwnProperty('ato') ? dir.ato : '/nolink'" > <template v-if="'submenus' in dir && dir.submenus.length > 0"> <template v-for="dir1 in dir.submenus"> <b-dropdown-hover-right :key="dir1.id" :c-text="dir1.name" :a-to="dir1.hasOwnProperty('ato') ? dir1.ato : '/nolink'" > <template v-if="'submenus' in dir1 && dir1.submenus.length > 0"> <template v-for="dir2 in dir1.submenus"> <b-dropdown-hover-right :key="dir2.id" :c-text="dir2.name" :a-to="dir2.hasOwnProperty('ato') ? dir2.ato : '/nolink'" > </b-dropdown-hover-right> </template> </template> </b-dropdown-hover-right> </template> </template> </b-dropdown-hover> </template> </b-navbar-nav> <!-- Right aligned nav items --> <b-navbar-nav class="ml-auto"> <b-nav-form> <b-form-input size="sm" class="mr-sm-2" placeholder="Search"></b-form-input> <b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button> </b-nav-form> <b-nav-item-dropdown right> <!-- Using 'button-content' slot --> <template #button-content> <b-img src="../assets/imgs/account-circle.svg" style="height: 35px"> </b-img> <!-- <em>User</em> --> </template> <b-dropdown-item href="#">Profile</b-dropdown-item> <b-dropdown-item href="#">Sign Out</b-dropdown-item> </b-nav-item-dropdown> </b-navbar-nav> </b-collapse> </b-navbar> <b-container id="app-content"> <Nuxt /> </b-container> <div id="footer"> <div style="height: 100%; padding: 5px">© 2021</div> </div> </div> </template> <script> import BDropdownHover from '@/components/BDropdownHover' import BDropdownHoverRight from '@/components/BDropdownHoverRight' export default { components: { BDropdownHover, BDropdownHoverRight, }, data() { return { navtop_dd: [ { id: 1, name: 'Transactions', ato: '/transactions', submenus: [ { id: '1a', name: 'Sales Orders', ato: '/transactions/salesorders', submenus: [ { id: '1b', name: 'New', }, { id: '2b', name: 'List', }, ], }, { id: '2a', name: 'Item Fulfillments', ato: '/transactions/itemfulfillments', submenus: [ { id: '1b', name: 'New', }, { id: '2b', name: 'List', }, ], }, ], }, { id: 2, name: 'Inventory', }, { id: 3, name: 'Reports', }, { id: 4, name: 'Setup', }, { id: 5, name: 'Support', }, ], } }, mounted() { var x = document.querySelectorAll('.b-dropdown.navtop-dd') for (var i = 0; i < x.length; i++) { if (x[i].querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length == 0) { var btn = x[i].querySelectorAll(':scope > .btn')[0] btn.classList += ' no-content-after' } } var x = document.querySelectorAll('.b-dropdown.ddr') for (var i = 0; i < x.length; i++) { if (x[i].querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length == 0) { var btn = x[i].querySelectorAll(':scope > .btn')[0] btn.classList += ' no-content-after' } } }, } </script> <style> #top-nav-bar { border-bottom: 1px solid green; } #tl-logo { height: 40px; margin: 5px; } #footer { height: 40px; color: black; border-top: 1px solid green; margin: auto; text-align: center; display: flex; align-items: center; justify-content: space-around; } .navtop-dd button { background: none !important; color: #6c757d !important; border: none !important; } #app-content { margin: 20px auto; } .ddr > button::after { display: inline-block; margin-left: 0.555em; right: 0px; content: ""; border-top: 0.25em solid transparent; border-right: 0.3em solid transparent; border-bottom: 0.25em solid transparent; border-left: 0.35em solid; vertical-align: 0.075em; } .b-dropdown { width: 100%; } .ddr > button { text-align: left; } .no-content-after::after { content: none !important; } .ddr > ul { top: -1.2rem; left: calc(100% - 0.5rem); } .dropdown-menu { min-width: 0 !important; } .dropdown-item { color: #6C757D; } .ddr-top:hover { background-color: #e4ffda; } a:hover { text-decoration: none !important; } </style>
P粉5692054782023-12-08 00:28:41
Il y a beaucoup de code non pertinent ici. J'ai pris le temps de le formater correctement. Merci de travailler dessus vous-même la prochaine fois (formatez et tapez uniquement les bits intéressants).
De plus, la vidéo elle-même donne déjà la réponse sur la façon de résoudre le problème. Cette vidéo discute de la différence entre les balises a
和 nuxt-link
.
Ceci est lié à la partie Bootstrap de la documentation Vue, que vous pouvez voir
Donc, vous devriez utiliser quelque chose comme ça
Custom Content with HTML via Slot Go to test page via Vue-router
J'ai également remarqué que votre code est très différent de la vidéo. Vous ne devriez pas utiliser querySelector
, vous n'avez pas besoin d'importer des composants Nuxt et vous recevrez plusieurs avertissements/erreurs ESlint.
Je recommande d’essayer de vous concentrer sur une seule partie de votre étude plutôt que de tout mélanger. C'est bien de vouloir aller plus loin, mais attention à ne pas se perdre dans trop d'abstractions quand on apprend beaucoup de nouveaux concepts (Vue/Nuxt).
D'ailleurs, si vous souhaitez continuer à apprendre Nuxt, vous pouvez consulter ceci : https://masteringnuxt.com/ (Créé par les ambassadeurs Nuxt et d'autres grands noms de l'écosystème Vue)
Amusez-vous à créer des projets avec Nuxt !