Javascript 在Vue 3中单击路由器链接时,如何在不重新加载页面的情况下切换侧栏
我有一个边栏组件,它的工作原理类似于模态。单击按钮时,侧边栏将转换为具有导航链接的视口。这些nav链路实际上是连接到vue路由器的路由器链路 我想要完成的事情 当我单击侧边栏组件内的路由器链接时,我希望侧边栏从视口中转移,并且我希望单击的路由器链接的组件在不重新加载页面的情况下呈现 目前发生了什么 当我单击router链接时,侧栏会立即从DOM中删除。它不能按预期在屏幕上进行转换。此外,页面将被重新加载 我还试过什么 我还尝试将Javascript 在Vue 3中单击路由器链接时,如何在不重新加载页面的情况下切换侧栏,javascript,html,vue.js,vue-component,vue-router,Javascript,Html,Vue.js,Vue Component,Vue Router,我有一个边栏组件,它的工作原理类似于模态。单击按钮时,侧边栏将转换为具有导航链接的视口。这些nav链路实际上是连接到vue路由器的路由器链路 我想要完成的事情 当我单击侧边栏组件内的路由器链接时,我希望侧边栏从视口中转移,并且我希望单击的路由器链接的组件在不重新加载页面的情况下呈现 目前发生了什么 当我单击router链接时,侧栏会立即从DOM中删除。它不能按预期在屏幕上进行转换。此外,页面将被重新加载 我还试过什么 我还尝试将包装器与相关的CSS类一起移动到sidebar.vue组件中,并将s
包装器与相关的CSS类一起移动到sidebar.vue
组件中,并将sidebarIsVisible
作为道具从App.vue
传递到sidebar.vue
我的代码
可以找到Codesandbox演示
App.vue
<template>
<router-view></router-view>
<button @click="toggleSidebar" class="toggleBtn">Toggle Sidebar</button>
<transition name="sidebar">
<the-sidebar
v-if="sidebarIsVisible"
@link-clicked="toggleSidebar"
></the-sidebar>
</transition>
</template>
<script>
import TheSidebar from "./components/TheSidebar.vue";
export default {
components: {
TheSidebar,
},
data() {
return {
sidebarIsVisible: false,
};
},
methods: {
toggleSidebar() {
this.sidebarIsVisible = !this.sidebarIsVisible;
},
closeSidebar() {
this.sidebarIsVisible = false;
},
},
};
</script>
<style>
/* basic styling */
.toggleBtn {
position: fixed;
top: 5px;
left: 5px;
}
.sidebar-enter-active {
animation: slide-sidebar 0.3s ease;
}
.sidebar-leave-active {
animation: slide-sidebar 0.3s ease reverse;
}
@keyframes slide-sidebar {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
</style>
<template>
<div class="sidebar">
<nav>
<ul>
<li>
<router-link @click="$emit('link-clicked')" to="/link1">
Link 1
</router-link>
</li>
<li>
<router-link @click="$emit('link-clicked')" to="/link2">
Link 2
</router-link>
</li>
</ul>
</nav>
</div>
</template>
<script>
export default {
emits: ["link-clicked"],
};
</script>
<style scoped>
/* basic styling */
</style>
main.js
import { createApp } from "vue";
import { createRouter, createWebHistory } from "vue-router";
import App from "./App.vue";
import LinkOne from "./components/LinkOne.vue";
import LinkTwo from "./components/LinkTwo.vue";
const app = createApp(App);
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/link1", component: LinkOne },
{ path: "/link2", component: LinkTwo }
]
});
app.use(router);
app.mount("#app");
有几件事我不确定,但我会尽力解释我认为正在发生的事情 首先,路由器链接上的点击事件是导致页面重新加载的原因,但我在文档中找不到任何提及这一预期行为的内容(这可能是值得的) 解决方法是将事件处理程序移动到
ul
上,并创建一个方法来确定是否单击了链接(下面的示例)
其次,这就是事情变得奇怪的地方,在VSCode中,在子组件的已发出事件中使用kebab case似乎可以阻止任何东西被发出,所以将它们更改为camelCase可以解决这个问题。但是,在CodeSandbox中尝试这一点根本不起作用,ESLint抱怨发出的事件应该是kebab事件。因此,在CodeSandbox中,情况正好相反:发出的事件名称应该是kebab case,侦听器应该是camelCase!完全不知道为什么,因为这与:
…当您在DOM模板中使用时,我们建议使用串壳事件侦听器
同样,我在文档中找不到任何明确说明在发出事件时需要使用camelCase的内容,它只是说在侦听事件时首选烤羊肉串
因此,总而言之,要使您的代码在VSCode中工作,并以符合文档建议的方式工作,您需要将其更改为:
<template>
<div class="sidebar">
<nav>
<!-- Move event here -->
<ul @click="handleClick($event)">
<li>
<router-link to="/link1">
Link 1
</router-link>
</li>
<li>
<router-link to="/link2">
Link 2
</router-link>
</li>
</ul>
</nav>
</div>
</template>
<script>
export default {
emits: ['linkClicked'], // Use camelCase for emitting
methods: {
handleClick(e) {
// Check the target is a link being clicked
if (e.target.localName !== 'a') return
this.$emit('linkClicked')
}
}
}
</script>
App.vue
:
@linkClicked="toggleSidebar"
如果有人能解释一下,那就太好了,因为我完全搞不懂这里发生了什么。太好了!标记作为答案。我真的很挣扎,最终选择了另一个方向,这是一个更“黑客”,甚至有一些问题。我将在此基础上进行重构。基本上,我所做的是删除路由器链接并添加作为参数传递路由器链接路径的单击侦听器。然后,我从sidebar.vue发出
link,点击到App.vue,通过this.$router.push(path)
将路径推送到我的路由器。但这似乎给我的历史状态带来了问题。非常感谢!
@linkClicked="toggleSidebar"