You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一页面多Vue应用间响应式localStorage状态共享问题

解决侧边栏切换时导航栏宽度同步变化的问题

首先修正你Sidebar.vue里的小问题:Vue Options API中,data返回的对象不需要用ref包裹(ref是Composition API语法),直接定义状态即可。

下面提供两种实用解决方案:

方案1:父子组件通信(适合简单场景)

假设导航栏组件(比如Navbar.vue)是Sidebar的父组件,按以下步骤修改:

1. 调整导航栏组件(Navbar.vue)

<template>
  <div class="navbar" :class="{ 'sidebar-expanded': isSidebarExpanded }">
    <!-- 导航栏自身内容 -->
    <Sidebar @toggle-sidebar="toggleSidebar" :is-expanded="isSidebarExpanded" />
  </div>
</template>

<script>
import Sidebar from './Sidebar.vue'

export default {
  components: { Sidebar },
  data() {
    return {
      isSidebarExpanded: localStorage.getItem('is_expanded') === 'true'
    }
  },
  methods: {
    toggleSidebar() {
      this.isSidebarExpanded = !this.isSidebarExpanded
      localStorage.setItem('is_expanded', this.isSidebarExpanded)
    }
  }
}
</script>

<style scoped>
.navbar {
  width: calc(100% - 60px); /* 侧边栏收起时的宽度,按需调整 */
  transition: width 0.3s ease; /* 平滑过渡动画 */
}

.navbar.sidebar-expanded {
  width: calc(100% - 250px); /* 侧边栏展开时的宽度,按需调整 */
}
</style>

2. 修改Sidebar.vue组件

把状态改为props接收,点击按钮时触发事件通知父组件:

<template>
  <aside :class="{ 'is-expanded': isExpanded }">
    <div class="head-aside">
      <div class="app-logo">
        <i class="bx bxl-trip-advisor"></i>
      </div>
      <span class="app-name">CONTROLPANEL</span>
    </div>

    <div class="menu-toggle-wrap">
      <button class="menu-toggle" @click="emitToggle">
        <span class="boxicons"><i :class="isExpanded ? 'bx bx-chevrons-left' : 'bx bx-chevrons-right'"></i></span>
      </button>
    </div>
  </aside>
</template>

<script>
export default {
  props: {
    isExpanded: {
      type: Boolean,
      required: true
    }
  },
  methods: {
    emitToggle() {
      this.$emit('toggle-sidebar')
    }
  }
}
</script>

方案2:用Pinia做状态管理(适合多组件共享状态)

如果项目中有多个组件需要用到侧边栏状态,用Pinia统一管理更高效:

1. 安装并配置Pinia

npm install pinia

在main.js中注册Pinia:

import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

2. 创建侧边栏状态Store

新建stores/sidebar.js:

import { defineStore } from 'pinia'

export const useSidebarStore = defineStore('sidebar', {
  state: () => ({
    isExpanded: localStorage.getItem('is_expanded') === 'true'
  }),
  actions: {
    toggle() {
      this.isExpanded = !this.isExpanded
      localStorage.setItem('is_expanded', this.isExpanded)
    }
  }
})

3. 修改Sidebar.vue组件

<template>
  <aside :class="{ 'is-expanded': sidebarStore.isExpanded }">
    <!-- 模板内容不变 -->
    <div class="menu-toggle-wrap">
      <button class="menu-toggle" @click="sidebarStore.toggle()">
        <span class="boxicons"><i :class="sidebarStore.isExpanded ? 'bx bx-chevrons-left' : 'bx bx-chevrons-right'"></i></span>
      </button>
    </div>
  </aside>
</template>

<script>
import { useSidebarStore } from '@/stores/sidebar'

export default {
  setup() {
    const sidebarStore = useSidebarStore()
    return { sidebarStore }
  }
}
</script>

4. 调整导航栏组件(Navbar.vue)

<template>
  <div class="navbar" :class="{ 'sidebar-expanded': sidebarStore.isExpanded }">
    <!-- 导航栏内容 -->
    <Sidebar />
  </div>
</template>

<script>
import Sidebar from './Sidebar.vue'
import { useSidebarStore } from '@/stores/sidebar'

export default {
  components: { Sidebar },
  setup() {
    const sidebarStore = useSidebarStore()
    return { sidebarStore }
  }
}
</script>

<style scoped>
.navbar {
  width: calc(100% - 60px);
  transition: width 0.3s ease;
}

.navbar.sidebar-expanded {
  width: calc(100% - 250px);
}
</style>

内容的提问来源于stack exchange,提问作者furaxsme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 17:40:54