{"id":458,"date":"2026-06-13T11:36:26","date_gmt":"2026-06-13T03:36:26","guid":{"rendered":"https:\/\/mitongxue.cn\/?p=458"},"modified":"2026-06-17T14:53:50","modified_gmt":"2026-06-17T06:53:50","slug":"react-dva-%e5%92%8c-vue-pinia","status":"publish","type":"post","link":"https:\/\/mitongxue.cn\/index.php\/2026\/06\/13\/react-dva-%e5%92%8c-vue-pinia\/","title":{"rendered":"React DVA\u00a0\u548c Vue (Pinia)"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\"><strong>1. React DVA \u793a\u4f8b<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5728 DVA \u4e2d\uff0c\u4f60\u9700\u8981\u5c06\u72b6\u6001\u3001\u540c\u6b65\u4fee\u6539\u3001\u5f02\u6b65\u8bf7\u6c42\u4e25\u683c\u5206\u79bb\uff0c\u5e76\u4f7f\u7528 Generator \u51fd\u6570\u5904\u7406\u5f02\u6b65\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Model \u5b9a\u4e49\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export default {\n  namespace: 'user',\n  state: {\n    userInfo: null,\n    loading: false\n  },\n  reducers: {\n    <em>\/\/ \u540c\u6b65\u4fee\u6539\uff1a\u5fc5\u987b\u8fd4\u56de\u65b0\u5bf9\u8c61\uff08\u4e0d\u53ef\u53d8\u6027\uff09<\/em>\n    saveUser(state, { payload }) {\n      return { ...state, userInfo: payload, loading: false };\n    },\n    setLoading(state, { payload }) {\n      return { ...state, loading: payload };\n    }\n  },\n  effects: {\n    <em>\/\/ \u5f02\u6b65\u64cd\u4f5c\uff1a\u4f7f\u7528 Generator \u51fd\u6570<\/em>\n    *fetchUser({ payload }, { call, put }) {\n      yield put({ type: 'setLoading', payload: true });\n      const response = yield call(api.getUserInfo, payload);\n      yield put({ type: 'saveUser', payload: response.data });\n    }\n  }\n};<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7ec4\u4ef6\u4f7f\u7528\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { connect } from 'dva';\n\nconst UserProfile = ({ user, dispatch }) =&gt; {\n  useEffect(() =&gt; {\n    <em>\/\/ \u89e6\u53d1 effects \u4e2d\u7684\u5f02\u6b65\u64cd\u4f5c<\/em>\n    dispatch({ type: 'user\/fetchUser', payload: { id: 1 } });\n  }, &#91;]);\n\n  return &lt;div&gt;{user.loading ? '\u52a0\u8f7d\u4e2d...' : user.userInfo?.name}&lt;\/div&gt;;\n};\n\n<em>\/\/ \u901a\u8fc7 connect \u6620\u5c04 state \u5230\u7ec4\u4ef6\u7684 props<\/em>\nexport default connect(({ user }) =&gt; ({ user }))(UserProfile);<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. Vue (Pinia) \u793a\u4f8b<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5728 Pinia \u4e2d\uff0c\u72b6\u6001\u4fee\u6539\u548c\u5f02\u6b65\u903b\u8f91\u53ef\u4ee5\u5408\u5e76\u5728&nbsp;<code>actions<\/code>&nbsp;\u4e2d\uff0c\u4ee3\u7801\u66f4\u52a0\u76f4\u89c2\u548c\u7d27\u51d1\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Store \u5b9a\u4e49\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { defineStore } from 'pinia';\n\nexport const useUserStore = defineStore('user', {\n  state: () =&gt; ({\n    userInfo: null,\n    loading: false\n  }),\n  actions: {\n    <em>\/\/ \u5f02\u6b65\u548c\u540c\u6b65\u64cd\u4f5c\u76f4\u63a5\u5199\u5728\u4e00\u8d77<\/em>\n    async fetchUser(id) {\n      this.loading = true; <em>\/\/ \u76f4\u63a5\u4fee\u6539 state\uff08Pinia \u5e95\u5c42\u81ea\u52a8\u8ffd\u8e2a\uff09<\/em>\n      const response = await api.getUserInfo(id);\n      this.userInfo = response.data; <em>\/\/ \u76f4\u63a5\u8d4b\u503c<\/em>\n      this.loading = false;\n    }\n  }\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7ec4\u4ef6\u4f7f\u7528\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script setup&gt;\nimport { storeToRefs } from 'pinia';\nimport { useUserStore } from '@\/stores\/user';\n\nconst userStore = useUserStore();\n<em>\/\/ \u4f7f\u7528 storeToRefs \u89e3\u6784\u4fdd\u6301\u54cd\u5e94\u5f0f<\/em>\nconst { loading, userInfo } = storeToRefs(userStore);\n\n<em>\/\/ \u76f4\u63a5\u8c03\u7528 action<\/em>\nuserStore.fetchUser(1);\n&lt;\/script&gt;\n\n&lt;template&gt;\n  &lt;div&gt;{{ loading ? '\u52a0\u8f7d\u4e2d...' : userInfo?.name }}&lt;\/div&gt;\n&lt;\/template&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u6838\u5fc3\u5dee\u5f02\u603b\u7ed3<\/strong><\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>\u5f02\u6b65\u8bed\u6cd5<\/strong>\uff1aDVA \u5fc5\u987b\u4f7f\u7528\u00a0<code>*fetchUser<\/code>\u00a0(Generator) +\u00a0<code>yield call<\/code>\u00a0+\u00a0<code>yield put<\/code>\uff1bVue \u53ea\u9700\u8981\u666e\u901a\u7684\u00a0<code>async fetchUser<\/code>\u00a0+\u00a0<code>await<\/code>\u3002<\/li>\n\n\n\n<li><strong>\u72b6\u6001\u4fee\u6539<\/strong>\uff1aDVA \u7684\u00a0<code>reducers<\/code>\u00a0\u5fc5\u987b\u00a0<code>return { ...state }<\/code>\u00a0\u8fd4\u56de\u65b0\u5bf9\u8c61\uff1bVue \u7684 Pinia \u53ef\u4ee5\u76f4\u63a5\u00a0<code>this.loading = true<\/code>\u00a0\u8d4b\u503c\u3002<\/li>\n\n\n\n<li><strong>\u7ec4\u4ef6\u7ed1\u5b9a<\/strong>\uff1aDVA \u9700\u8981\u00a0<code>connect<\/code>\u00a0\u5305\u88f9\u7ec4\u4ef6\u5e76\u624b\u52a8\u6620\u5c04 props\uff1bVue \u53ea\u9700\u00a0<code>useUserStore()<\/code>\u00a0\u5f15\u5165\u5373\u53ef\uff0c\u6a21\u677f\u81ea\u52a8\u54cd\u5e94\u6570\u636e\u53d8\u5316\u3002<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. React DVA \u793a\u4f8b \u5728 DVA \u4e2d\uff0c\u4f60..<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,13,11],"tags":[],"class_list":["post-458","post","type-post","status-publish","format-standard","hentry","category-react-","category-vue","category-front"],"featured_image_urls":{"full":"","thumbnail":"","medium":"","medium_large":"","large":"","1536x1536":"","2048x2048":""},"author_info":{"info":["\u9648 \u67d0\u4eba"]},"category_info":"<a href=\"https:\/\/mitongxue.cn\/index.php\/category\/front\/react-%e5%89%8d%e7%ab%af\/\" rel=\"category tag\">React<\/a> <a href=\"https:\/\/mitongxue.cn\/index.php\/category\/front\/vue\/\" rel=\"category tag\">Vue<\/a> <a href=\"https:\/\/mitongxue.cn\/index.php\/category\/front\/\" rel=\"category tag\">\u524d\u7aef<\/a>","tag_info":"\u524d\u7aef","comment_count":"0","_links":{"self":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/458","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/comments?post=458"}],"version-history":[{"count":1,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/458\/revisions"}],"predecessor-version":[{"id":459,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/458\/revisions\/459"}],"wp:attachment":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/media?parent=458"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/categories?post=458"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/tags?post=458"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}