Vue复杂应用组件显隐切换实现方法(笔记应用场景)
Hey there! Since you're a Vue newbie working on your notes app and learning Vuex, let's walk through exactly how to toggle between your NotesList and MessagesList components when clicking that "Messages" button. This is a super common UI pattern, so once you get the hang of it, it'll feel second nature!
基础实现(本地组件状态)
If you just want to get the toggle working first without diving into Vuex, you can start with local state in the parent component (like your main App component or the component holding the toolbar):
- Define a reactive state property to track which view is active
- Use
v-if(orv-showif you prefer toggling visibility instead of mounting/unmounting) to control which component renders - Add a click handler to your "Messages" button to switch the active view
Here's a quick example with Vue 2's Options API:
<template> <div class="app-wrapper"> <!-- Toolbar with your buttons --> <div class="toolbar"> <button @click="switchToNotes">笔记</button> <button @click="switchToMessages">消息</button> </div> <!-- Conditionally render components --> <NotesList v-if="activeView === 'notes'" /> <MessagesList v-if="activeView === 'messages'" /> </div> </template> <script> import NotesList from './components/NotesList.vue' import MessagesList from './components/MessagesList.vue' export default { components: { NotesList, MessagesList }, data() { return { activeView: 'notes' // Start with notes visible by default } }, methods: { switchToNotes() { this.activeView = 'notes' }, switchToMessages() { this.activeView = 'messages' } } } </script>
结合Vuex的全局状态管理
Since you're learning Vuex, let's adapt this to use global state—this is great if you need to access the active view state from other components later on:
Step 1: Update your Vuex Store
Add a state property, mutation, and optional action to manage the active view:
// store/index.js import { createStore } from 'vuex' export default createStore({ state: { activeView: 'notes' // Default view }, mutations: { // Mutations are for sync state updates SET_ACTIVE_VIEW(state, viewName) { state.activeView = viewName } }, actions: { // Actions are for async operations (optional here, but good practice) setActiveView({ commit }, viewName) { commit('SET_ACTIVE_VIEW', viewName) } }, getters: { // Optional: Getter to access the state cleanly activeView: state => state.activeView } })
Step 2: Use Vuex in Your Parent Component
Vue 2 Options API:
<template> <div class="app-wrapper"> <div class="toolbar"> <button @click="setActiveView('notes')">笔记</button> <button @click="setActiveView('messages')">消息</button> </div> <NotesList v-if="activeView === 'notes'" /> <MessagesList v-if="activeView === 'messages'" /> </div> </template> <script> import NotesList from './components/NotesList.vue' import MessagesList from './components/MessagesList.vue' import { mapState, mapActions } from 'vuex' export default { components: { NotesList, MessagesList }, computed: { // Map the Vuex state to a local computed property ...mapState(['activeView']) }, methods: { // Map the Vuex action to a local method ...mapActions(['setActiveView']) } } </script>
Vue 3 Composition API:
<template> <div class="app-wrapper"> <div class="toolbar"> <button @click="updateActiveView('notes')">笔记</button> <button @click="updateActiveView('messages')">消息</button> </div> <NotesList v-if="activeView === 'notes'" /> <MessagesList v-if="activeView === 'messages'" /> </div> </template> <script setup> import NotesList from './components/NotesList.vue' import MessagesList from './components/MessagesList.vue' import { useStore } from 'vuex' import { computed } from 'vue' const store = useStore() // Access the Vuex state via a computed property const activeView = computed(() => store.state.activeView) const updateActiveView = (viewName) => { // Dispatch the action (or commit the mutation directly if no async work) store.dispatch('setActiveView', viewName) } </script>
更简洁的动态组件方式
If you want to clean up your template a bit, you can use Vue's <component :is="..."> syntax to dynamically render the active component:
<template> <div class="app-wrapper"> <div class="toolbar"> <button @click="updateActiveView('notes')">笔记</button> <button @click="updateActiveView('messages')">消息</button> </div> <!-- Dynamically render the correct component --> <component :is="currentComponent" /> </div> </template> <script setup> import NotesList from './components/NotesList.vue' import MessagesList from './components/MessagesList.vue' import { useStore } from 'vuex' import { computed } from 'vue' const store = useStore() const activeView = computed(() => store.state.activeView) // Map the active view string to the actual component const currentComponent = computed(() => { return activeView.value === 'notes' ? NotesList : MessagesList }) const updateActiveView = (viewName) => { store.commit('SET_ACTIVE_VIEW', viewName) } </script>
Quick Notes:
- Use
v-ifif you want the component to be mounted/unmounted when toggling (good for performance if components are heavy) - Use
v-showif you just want to toggle visibility (components stay mounted, better for frequent toggles) - Vuex is useful here if you need to share the active view state across multiple components—if it's only needed in this one parent/child setup, local state works just fine!
内容的提问来源于stack exchange,提问作者Rasim AVCI

