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

如何在Vue中向Pinia Getter传递参数?附代码示例

问题:Pinia带参数Getter无法正确传递ID获取对应Thread

我想在组件的computed中映射Pinia store里的thread getter,并在模板中使用,但无法正确传递ID参数来获取对应的thread。原本教程用Vuex,现在转Pinia过程中遇到了困惑。


ThreadsStore 代码

import { defineStore } from "pinia";
import sourceData from "@/data.json";
import { useUsersStore } from "../stores/UsersStore";
import { usePostsStore } from "../stores/PostsStore";
import { useForumsStore } from "../stores/ForumsStore";
import { findById, upsert } from "@/helpers";

export const useThreadsStore = defineStore("ThreadsStore", {
  state: () => {
    return {
      threads: sourceData.threads,
    };
  },
  getters: {
    thread: (state) => {
      return (id) => {
        const thread = findById(state.threads, id);
        return {
          ...thread,
          get author() {
            return findById(useUsersStore().users, thread.userId);
          },
          get repliesCount() {
            return thread.posts.length - 1;
          },
          get contributorsCount() {
            return thread.contributors.length;
          },
        };
      };
    },
  },
  actions: {
    async createThread({ text, title, forumId }) {
      const id = "ggqq" + Math.random();
      const userId = useUsersStore().authId;
      const publishedAt = Math.floor(Date.now() / 1000);
      const thread = { forumId, title, publishedAt, userId, id };

      this.threads.push(thread);
      this.appendThreadToUser({ userId, threadId: id });
      this.appendThreadToForum({ forumId, threadId: id });
      usePostsStore().createPost({ text, threadId: id });

      return findById(this.threads, id);
    },
    async updateThread({ title, text, id }) {
      const thread = findById(this.threads, id);
      const post = findById(usePostsStore().posts, thread.posts[0]);
      const newThread = { ...thread, title };
      const newPost = { ...post, text };
      this.setThread({ thread: newThread });
      this.setPost({ post: newPost });
      return newThread;
    },
    appendThreadToForum({ forumId, threadId }) {
      const forum = findById(useForumsStore().forums, forumId);
      forum.threads = forum.threads || [];
      forum.threads.push(threadId);
    },
    appendThreadToUser({ userId, threadId }) {
      const user = findById(useUsersStore().users, userId);
      user.threads = user.threads || [];
      user.threads.push(threadId);
    },
    setPost({ post }) {
      upsert(usePostsStore().posts, post);
    },
    setThread({ thread }) {
      upsert(this.threads, thread);
    },
  },
});

页面组件代码

<template>
  <div class="col-large push-top">
    <h1>
      {{ thread.title }}
      <router-link
        :to="{ name: 'ThreadEdit', id: this.id }"
        class="btn-green btn-small"
      >
        Edit Thread
      </router-link>
    </h1>

    <p>
      By <a href="#" class="link-unstyled">{{ thread.author.name }}</a
      >, <AppDate :timestamp="thread.publishedAt" />.
      <span
        style="float: right; margin-top: 2px"
        class="hide-mobile text-faded text-small"
        >{{ thread.repliesCount }} replies by
        {{ thread.contributorsCount }} contributors</span
      >
    </p>

    <post-list :posts="threadPosts" />

    <post-editor @save="addPost" />
  </div>
</template>

<script>
import { mapState, mapActions } from "pinia";
import { useThreadsStore } from "../stores/ThreadsStore";
import { usePostsStore } from "../stores/PostsStore";
import PostList from "@/components/PostList";
import PostEditor from "@/components/PostEditor";

export default {
  name: "ThreadShow",
  components: {
    PostList,
    PostEditor,
  },
  props: {
    id: {
      required: true,
      type: String,
    },
  },
  computed: {
    ...mapState(useThreadsStore, ["threads", "thread"]),
    ...mapState(usePostsStore, ["posts"]),
    threadPosts() {
      return this.posts.filter((post) => post.threadId === this.id);
    },
  },
  methods: {
    ...mapActions(usePostsStore, ["createPost"]),
    addPost(eventData) {
      const post = {
        ...eventData.post,
        threadId: this.id,
      };
      this.createPost(post);
    },
  },
};
</script>

解决方案

问题出在Pinia的带参数Getter不能直接通过mapState映射后在模板中直接访问属性。mapState会把thread getter作为一个函数映射到组件中,模板里的{{ thread.title }}实际上是在访问这个函数的title属性,自然取不到正确值。

修改组件的computed部分,手动定义thread计算属性,调用store的thread getter并传入当前组件的id参数:

<script>
import { mapState, mapActions } from "pinia";
import { useThreadsStore } from "../stores/ThreadsStore";
import { usePostsStore } from "../stores/PostsStore";
import PostList from "@/components/PostList";
import PostEditor from "@/components/PostEditor";

export default {
  name: "ThreadShow",
  components: {
    PostList,
    PostEditor,
  },
  props: {
    id: {
      required: true,
      type: String,
    },
  },
  computed: {
    ...mapState(useThreadsStore, ["threads"]), // 移除对`thread`的映射
    ...mapState(usePostsStore, ["posts"]),
    thread() {
      // 手动调用store的thread getter并传入id
      const threadsStore = useThreadsStore();
      return threadsStore.thread(this.id);
    },
    threadPosts() {
      return this.posts.filter((post) => post.threadId === this.id);
    },
  },
  methods: {
    ...mapActions(usePostsStore, ["createPost"]),
    addPost(eventData) {
      const post = {
        ...eventData.post,
        threadId: this.id,
      };
      this.createPost(post);
    },
  },
};
</script>

也可以选择不使用mapState,直接在computed中获取store实例:

computed: {
  threadsStore() {
    return useThreadsStore();
  },
  postsStore() {
    return usePostsStore();
  },
  thread() {
    return this.threadsStore.thread(this.id);
  },
  threadPosts() {
    return this.postsStore.posts.filter((post) => post.threadId === this.id);
  },
},

这样就能正确获取到对应ID的thread,并在模板中访问它的属性了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:55:24