Vue:如何正确连接 Pinia 商店、路由器和 UI 工具栏以共享全局状态变量

问题描述 投票:0回答:1

给出 Vue 3 和 Quasar 上的应用程序。
该应用程序管理一些配置,但一次只能管理一项。所以有一个“当前配置”的概念,它只是一个字符串(名称)。
我想在应用程序的工具栏中有一个下拉菜单,其中包含当前配置选择为活动状态的所有配置)。当它被选择时,它应该反映在 URL 参数中(如 &config=name1),无论当前路由如何。在应用程序启动时,如果 URL 中有配置,则应解析该配置并将其设置为当前配置名称。 但是路由器和工具栏的下拉菜单应该一起工作但相互隔离。所有其他组件都应使用商店的字段

currentConfig
。这家商店位于皮尼亚。 该商店的字段应该连接到路由器:
当我更改 store.currentConfig 时,它会自动更改 URL 参数和工具栏 反之亦然:工具栏中当前选择的配置应始终反映在商店的字段中。

如何将这三个实体正确绑定在一起?

我做了什么。 在工具栏中:

          <q-list>
            <q-item v-for="t in store.configs" :key="`${t.name}`" clickable v-close-popup tabindex="0"
              @click="store.currentConfig = t.name" :active="store.currentConfig == t.name">
              <q-item-section>
                <q-item-label>{{ t.name }}</q-item-label>
              </q-item-section>
            </q-item>
          </q-list>

即在选择配置时,我们只需设置商店的字段。

在我的商店(stores/configuration.ts)中,我有一个州的字段:

export const configurationStore = defineStore('configuration', {
  state: () => ({
    currentConfig: ''
  })
});

我想对店内的变化做出反应。看起来在这样的处理程序中,它是放置 URL 参数的好地方。 但我看不到订阅其 iwn 商店更改的方法:(

vue.js vuejs3 vue-router pinia
1个回答
1
投票

我会这样做:

// router/index.js
import { createRouter, createWebHistory } from "vue-router";

const routes = [
{
    path: "/",
    name: "Home",
    component: () => import("../views/Home.vue"),
    props: (route) => ({ config: route.query.config || "" }), // Capture 'config' from URL
},
// Other routes
];

const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});

export default router;

然后添加 pinia 配置,如下所示:

// stores/configuration.ts
import { defineStore } from "pinia";

export const useConfigurationStore = defineStore("configuration", {
state: () => ({
    currentConfig: "",
}),
actions: {
    setCurrentConfig(configName) {
    this.currentConfig = configName;
    },
},
});

然后,主 Vue 应用程序:在主 Vue 应用程序中,您可以使用计算属性将商店的状态与 URL 参数同步。另外,当商店的 currentConfig 发生变化时,可以使用手表来更新 URL 参数。

// main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { useConfigurationStore } from "./stores/configuration";

const app = createApp(App);
app.use(router);

const store = useConfigurationStore();

app.config.globalProperties.$store = store;

app.mount("#app");

// Synchronize store state with URL parameter
const configFromRoute = router.currentRoute.value.query.config;
if (configFromRoute) {
store.setCurrentConfig(configFromRoute);
}

// Watch for changes in the store's currentConfig and update the URL parameter
store.$watch(
(state) => state.currentConfig,
(newConfig) => {
    router.push({ query: { config: newConfig } });
}
);

然后是下拉组件中有趣的部分:

<!-- Dropdown.vue -->
<template>
<select v-model="currentConfig">
    <option v-for="config in configs" :key="config.name" :value="config.name">
    {{ config.name }}
    </option>
</select>
</template>

<script>
import { computed } from "vue";
import { useConfigurationStore } from "@/stores/configuration";

export default {
name: "Dropdown",
setup() {
    const store = useConfigurationStore();
    const currentConfig = computed({
    get: () => store.currentConfig,
    set: (value) => store.setCurrentConfig(value),
    });

    const configs = [
    // Your list of configuration options
    ];

    return {
    currentConfig,
    configs,
    };
},
};
</script>
© www.soinside.com 2019 - 2024. All rights reserved.