{"id":55188,"date":"2025-08-13T18:54:38","date_gmt":"2025-08-13T10:54:38","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/55188.html"},"modified":"2025-08-13T18:54:38","modified_gmt":"2025-08-13T10:54:38","slug":"vue3%e5%85%a5%e9%97%a8%e6%95%99%e7%a8%8bvue3%e7%8a%b6%e6%80%81%e7%ae%a1%e7%90%86pinia%e7%94%a8%e6%b3%95%e8%af%a6%e8%a7%a3","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/55188.html","title":{"rendered":"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3"},"content":{"rendered":"<h2 id=\"-pinia-\u7b80\u4ecb\">Pinia \u7b80\u4ecb<\/h2>\n<p>Pinia\u662fVue3\u7684\u5b98\u65b9\u72b6\u6001\u7ba1\u7406\u5e93&#xff0c;\u5b83\u63d0\u4f9b\u4e86\u7b80\u5355\u3001\u76f4\u89c2\u7684\u72b6\u6001\u7ba1\u7406\u89e3\u51b3\u65b9\u6848&#xff0c;\u4e0eVue3\u7684Composition API\u5b8c\u7f8e\u96c6\u6210\u3002<\/p>\n<h3 id=\"\u4e3b\u8981\u7279\u6027\">\u4e3b\u8981\u7279\u6027<\/h3>\n<ul>\n<li>TypeScript\u652f\u6301&#xff1a;\u5b8c\u6574\u7684TypeScript\u7c7b\u578b\u63a8\u65ad<\/li>\n<li>\u8f7b\u91cf\u7ea7&#xff1a;\u4f53\u79ef\u5c0f&#xff0c;\u6027\u80fd\u4f18\u79c0<\/li>\n<li>DevTools\u652f\u6301&#xff1a;\u4f18\u79c0\u7684\u5f00\u53d1\u5de5\u5177\u652f\u6301<\/li>\n<li>\u6a21\u5757\u5316&#xff1a;\u652f\u6301\u591a\u4e2aStore<\/li>\n<li>\u7ec4\u5408\u5f0fAPI&#xff1a;\u4e0eVue3 Composition API\u5b8c\u7f8e\u96c6\u6210<\/li>\n<\/ul>\n<h2 id=\"-store-\u7684\u5b9a\u4e49\u548c\u521b\u5efa\">Store \u7684\u5b9a\u4e49\u548c\u521b\u5efa<\/h2>\n<h3 id=\"\u57fa\u7840store\u5b9a\u4e49\">\u57fa\u7840Store\u5b9a\u4e49<\/h3>\n<p>\/\/ stores\/counter.js<br \/>\nimport { defineStore } from &#039;pinia&#039;<br \/>\nimport { ref, computed } from &#039;vue&#039;<\/p>\n<p>export const useCounterStore &#061; defineStore(&#039;counter&#039;, () &#061;&gt; {<br \/>\n  \/\/ \u72b6\u6001<br \/>\n  const count &#061; ref(0)<br \/>\n  const name &#061; ref(&#039;Counter Store&#039;)<\/p>\n<p>  \/\/ \u8ba1\u7b97\u5c5e\u6027<br \/>\n  const doubleCount &#061; computed(() &#061;&gt; count.value * 2)<br \/>\n  const isEven &#061; computed(() &#061;&gt; count.value % 2 &#061;&#061;&#061; 0)<\/p>\n<p>  \/\/ \u65b9\u6cd5<br \/>\n  function increment() {<br \/>\n    count.value&#043;&#043;<br \/>\n  }<\/p>\n<p>  function decrement() {<br \/>\n    count.value&#8211;<br \/>\n  }<\/p>\n<p>  function reset() {<br \/>\n    count.value &#061; 0<br \/>\n  }<\/p>\n<p>  function setCount(value) {<br \/>\n    count.value &#061; value<br \/>\n  }<\/p>\n<p>  \/\/ \u5f02\u6b65\u65b9\u6cd5<br \/>\n  async function incrementAsync() {<br \/>\n    await new Promise(resolve &#061;&gt; setTimeout(resolve, 1000))<br \/>\n    count.value&#043;&#043;<br \/>\n  }<\/p>\n<p>  return {<br \/>\n    \/\/ \u72b6\u6001<br \/>\n    count,<br \/>\n    name,<br \/>\n    \/\/ \u8ba1\u7b97\u5c5e\u6027<br \/>\n    doubleCount,<br \/>\n    isEven,<br \/>\n    \/\/ \u65b9\u6cd5<br \/>\n    increment,<br \/>\n    decrement,<br \/>\n    reset,<br \/>\n    setCount,<br \/>\n    incrementAsync<br \/>\n  }<br \/>\n})<\/p>\n<h2 id=\"-store-\u7684\u4f7f\u7528\">Store \u7684\u4f7f\u7528<\/h2>\n<h3 id=\"\u5728\u7ec4\u4ef6\u4e2d\u4f7f\u7528store\">\u5728\u7ec4\u4ef6\u4e2d\u4f7f\u7528Store<\/h3>\n<p>&lt;!&#8211; components\/CounterDemo.vue &#8211;&gt;<br \/>\n&lt;template&gt;<br \/>\n  &lt;div class&#061;&#034;counter-demo&#034;&gt;<br \/>\n    &lt;h2&gt;\u8ba1\u6570\u5668\u793a\u4f8b&lt;\/h2&gt;<\/p>\n<p>    &lt;!&#8211; \u76f4\u63a5\u4f7f\u7528Store\u72b6\u6001 &#8211;&gt;<br \/>\n    &lt;div class&#061;&#034;counter-info&#034;&gt;<br \/>\n      &lt;p&gt;\u5f53\u524d\u8ba1\u6570&#xff1a;{{ counterStore.count }}&lt;\/p&gt;<br \/>\n      &lt;p&gt;\u53cc\u500d\u8ba1\u6570&#xff1a;{{ counterStore.doubleCount }}&lt;\/p&gt;<br \/>\n      &lt;p&gt;\u662f\u5426\u5076\u6570&#xff1a;{{ counterStore.isEven ? &#039;\u662f&#039; : &#039;\u5426&#039; }}&lt;\/p&gt;<br \/>\n      &lt;p&gt;Store\u540d\u79f0&#xff1a;{{ counterStore.name }}&lt;\/p&gt;<br \/>\n    &lt;\/div&gt;<\/p>\n<p>    &lt;!&#8211; \u64cd\u4f5c\u6309\u94ae &#8211;&gt;<br \/>\n    &lt;div class&#061;&#034;counter-actions&#034;&gt;<br \/>\n      &lt;button &#064;click&#061;&#034;counterStore.increment&#034;&gt;&#043;1&lt;\/button&gt;<br \/>\n      &lt;button &#064;click&#061;&#034;counterStore.decrement&#034;&gt;-1&lt;\/button&gt;<br \/>\n      &lt;button &#064;click&#061;&#034;counterStore.reset&#034;&gt;\u91cd\u7f6e&lt;\/button&gt;<br \/>\n      &lt;button &#064;click&#061;&#034;counterStore.incrementAsync&#034; :disabled&#061;&#034;loading&#034;&gt;<br \/>\n        {{ loading ? &#039;\u52a0\u8f7d\u4e2d&#8230;&#039; : &#039;\u5f02\u6b65&#043;1&#039; }}<br \/>\n      &lt;\/button&gt;<br \/>\n    &lt;\/div&gt;<\/p>\n<p>    &lt;!&#8211; \u81ea\u5b9a\u4e49\u8f93\u5165 &#8211;&gt;<br \/>\n    &lt;div class&#061;&#034;counter-input&#034;&gt;<br \/>\n      &lt;input v-model.number&#061;&#034;newValue&#034; type&#061;&#034;number&#034; placeholder&#061;&#034;\u8bbe\u7f6e\u65b0\u503c&#034;&gt;<br \/>\n      &lt;button &#064;click&#061;&#034;setCustomValue&#034;&gt;\u8bbe\u7f6e&lt;\/button&gt;<br \/>\n    &lt;\/div&gt;<\/p>\n<p>    &lt;!&#8211; \u7528\u6237Store\u793a\u4f8b &#8211;&gt;<br \/>\n    &lt;div class&#061;&#034;user-info&#034; v-if&#061;&#034;userStore.isAuthenticated&#034;&gt;<br \/>\n      &lt;h3&gt;\u7528\u6237\u4fe1\u606f&lt;\/h3&gt;<br \/>\n      &lt;p&gt;\u7528\u6237\u540d&#xff1a;{{ userStore.userName }}&lt;\/p&gt;<br \/>\n      &lt;p&gt;\u7528\u6237\u4fe1\u606f&#xff1a;{{ userStore.userInfo }}&lt;\/p&gt;<br \/>\n      &lt;p&gt;\u662f\u5426\u6709\u7ba1\u7406\u6743\u9650&#xff1a;{{ userStore.hasPermission(&#039;admin&#039;) ? &#039;\u662f&#039; : &#039;\u5426&#039; }}&lt;\/p&gt;<br \/>\n      &lt;button &#064;click&#061;&#034;userStore.logout&#034;&gt;\u767b\u51fa&lt;\/button&gt;<br \/>\n    &lt;\/div&gt;<\/p>\n<p>    &lt;div v-else class&#061;&#034;login-form&#034;&gt;<br \/>\n      &lt;h3&gt;\u767b\u5f55&lt;\/h3&gt;<br \/>\n      &lt;input v-model&#061;&#034;loginForm.username&#034; placeholder&#061;&#034;\u7528\u6237\u540d&#034;&gt;<br \/>\n      &lt;input v-model&#061;&#034;loginForm.password&#034; type&#061;&#034;password&#034; placeholder&#061;&#034;\u5bc6\u7801&#034;&gt;<br \/>\n      &lt;button &#064;click&#061;&#034;handleLogin&#034; :disabled&#061;&#034;loginLoading&#034;&gt;<br \/>\n        {{ loginLoading ? &#039;\u767b\u5f55\u4e2d&#8230;&#039; : &#039;\u767b\u5f55&#039; }}<br \/>\n      &lt;\/button&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n  &lt;\/div&gt;<br \/>\n&lt;\/template&gt;<\/p>\n<p>&lt;script setup&gt;<br \/>\nimport { ref, onMounted } from &#039;vue&#039;<br \/>\nimport { useCounterStore } from &#039;..\/stores\/counter&#039;<br \/>\nimport { useUserStore } from &#039;..\/stores\/user&#039;<\/p>\n<p>\/\/ \u4f7f\u7528Store<br \/>\nconst counterStore &#061; useCounterStore()<br \/>\nconst userStore &#061; useUserStore()<\/p>\n<p>\/\/ \u672c\u5730\u72b6\u6001<br \/>\nconst newValue &#061; ref(0)<br \/>\nconst loading &#061; ref(false)<br \/>\nconst loginForm &#061; ref({<br \/>\n  username: &#039;&#039;,<br \/>\n  password: &#039;&#039;<br \/>\n})<br \/>\nconst loginLoading &#061; ref(false)<\/p>\n<p>\/\/ \u8bbe\u7f6e\u81ea\u5b9a\u4e49\u503c<br \/>\nconst setCustomValue &#061; () &#061;&gt; {<br \/>\n  counterStore.setCount(newValue.value)<br \/>\n}<\/p>\n<p>\/\/ \u5904\u7406\u767b\u5f55<br \/>\nconst handleLogin &#061; async () &#061;&gt; {<br \/>\n  if (!loginForm.value.username || !loginForm.value.password) {<br \/>\n    alert(&#039;\u8bf7\u8f93\u5165\u7528\u6237\u540d\u548c\u5bc6\u7801&#039;)<br \/>\n    return<br \/>\n  }<\/p>\n<p>  loginLoading.value &#061; true<br \/>\n  try {<br \/>\n    const result &#061; await userStore.login(loginForm.value)<br \/>\n    if (result.success) {<br \/>\n      alert(&#039;\u767b\u5f55\u6210\u529f&#xff01;&#039;)<br \/>\n      loginForm.value &#061; { username: &#039;&#039;, password: &#039;&#039; }<br \/>\n    } else {<br \/>\n      alert(&#096;\u767b\u5f55\u5931\u8d25&#xff1a;${result.error}&#096;)<br \/>\n    }<br \/>\n  } finally {<br \/>\n    loginLoading.value &#061; false<br \/>\n  }<br \/>\n}<\/p>\n<p>\/\/ \u7ec4\u4ef6\u6302\u8f7d\u65f6\u521d\u59cb\u5316\u7528\u6237\u72b6\u6001<br \/>\nonMounted(async () &#061;&gt; {<br \/>\n  await userStore.initUser()<br \/>\n})<br \/>\n&lt;\/script&gt;<\/p>\n<p>&lt;style scoped&gt;<br \/>\n.counter-demo {<br \/>\n  padding: 20px;<br \/>\n  max-width: 600px;<br \/>\n  margin: 0 auto;<br \/>\n}<\/p>\n<p>.counter-info {<br \/>\n  background: #f8f9fa;<br \/>\n  padding: 15px;<br \/>\n  border-radius: 8px;<br \/>\n  margin-bottom: 20px;<br \/>\n}<\/p>\n<p>.counter-actions {<br \/>\n  display: flex;<br \/>\n  gap: 10px;<br \/>\n  margin-bottom: 20px;<br \/>\n}<\/p>\n<p>.counter-actions button {<br \/>\n  padding: 10px 20px;<br \/>\n  background: #007bff;<br \/>\n  color: white;<br \/>\n  border: none;<br \/>\n  border-radius: 4px;<br \/>\n  cursor: pointer;<br \/>\n}<\/p>\n<p>.counter-actions button:hover {<br \/>\n  background: #0056b3;<br \/>\n}<\/p>\n<p>.counter-actions button:disabled {<br \/>\n  background: #6c757d;<br \/>\n  cursor: not-allowed;<br \/>\n}<\/p>\n<p>.counter-input {<br \/>\n  display: flex;<br \/>\n  gap: 10px;<br \/>\n  margin-bottom: 20px;<br \/>\n}<\/p>\n<p>.counter-input input {<br \/>\n  padding: 8px;<br \/>\n  border: 1px solid #ddd;<br \/>\n  border-radius: 4px;<br \/>\n  flex: 1;<br \/>\n}<\/p>\n<p>.counter-input button {<br \/>\n  padding: 8px 16px;<br \/>\n  background: #28a745;<br \/>\n  color: white;<br \/>\n  border: none;<br \/>\n  border-radius: 4px;<br \/>\n  cursor: pointer;<br \/>\n}<\/p>\n<p>.user-info,<br \/>\n.login-form {<br \/>\n  background: #e9ecef;<br \/>\n  padding: 15px;<br \/>\n  border-radius: 8px;<br \/>\n  margin-top: 20px;<br \/>\n}<\/p>\n<p>.login-form input {<br \/>\n  display: block;<br \/>\n  width: 100%;<br \/>\n  padding: 8px;<br \/>\n  margin: 10px 0;<br \/>\n  border: 1px solid #ddd;<br \/>\n  border-radius: 4px;<br \/>\n}<\/p>\n<p>.login-form button {<br \/>\n  width: 100%;<br \/>\n  padding: 10px;<br \/>\n  background: #007bff;<br \/>\n  color: white;<br \/>\n  border: none;<br \/>\n  border-radius: 4px;<br \/>\n  cursor: pointer;<br \/>\n}<br \/>\n&lt;\/style&gt;<\/p>\n<h3 id=\"42-\u9ad8\u7ea7\u72b6\u6001\u7ba1\u7406\">\u9ad8\u7ea7\u72b6\u6001\u7ba1\u7406<\/h3>\n<h5 id=\"\u8d2d\u7269\u8f66store\u793a\u4f8b\">\u8d2d\u7269\u8f66Store\u793a\u4f8b<\/h5>\n<p>\/\/ stores\/cart.js<br \/>\nimport { defineStore } from &#039;pinia&#039;<br \/>\nimport { ref, computed } from &#039;vue&#039;<\/p>\n<p>export const useCartStore &#061; defineStore(&#039;cart&#039;, () &#061;&gt; {<br \/>\n  \/\/ \u72b6\u6001<br \/>\n  const items &#061; ref([])<br \/>\n  const isLoading &#061; ref(false)<\/p>\n<p>  \/\/ \u8ba1\u7b97\u5c5e\u6027<br \/>\n  const totalItems &#061; computed(() &#061;&gt; {<br \/>\n    return items.value.reduce((total, item) &#061;&gt; total &#043; item.quantity, 0)<br \/>\n  })<\/p>\n<p>  const totalPrice &#061; computed(() &#061;&gt; {<br \/>\n    return items.value.reduce((total, item) &#061;&gt; total &#043; item.price * item.quantity, 0)<br \/>\n  })<\/p>\n<p>  const isEmpty &#061; computed(() &#061;&gt; items.value.length &#061;&#061;&#061; 0)<\/p>\n<p>  const itemCount &#061; computed(() &#061;&gt; items.value.length)<\/p>\n<p>  \/\/ \u65b9\u6cd5<br \/>\n  function addItem(product, quantity &#061; 1) {<br \/>\n    const existingItem &#061; items.value.find(item &#061;&gt; item.id &#061;&#061;&#061; product.id)<\/p>\n<p>    if (existingItem) {<br \/>\n      existingItem.quantity &#043;&#061; quantity<br \/>\n    } else {<br \/>\n      items.value.push({<br \/>\n        &#8230;product,<br \/>\n        quantity<br \/>\n      })<br \/>\n    }<br \/>\n  }<\/p>\n<p>  function removeItem(productId) {<br \/>\n    const index &#061; items.value.findIndex(item &#061;&gt; item.id &#061;&#061;&#061; productId)<br \/>\n    if (index &gt; -1) {<br \/>\n      items.value.splice(index, 1)<br \/>\n    }<br \/>\n  }<\/p>\n<p>  function updateQuantity(productId, quantity) {<br \/>\n    const item &#061; items.value.find(item &#061;&gt; item.id &#061;&#061;&#061; productId)<br \/>\n    if (item) {<br \/>\n      if (quantity &lt;&#061; 0) {<br \/>\n        removeItem(productId)<br \/>\n      } else {<br \/>\n        item.quantity &#061; quantity<br \/>\n      }<br \/>\n    }<br \/>\n  }<\/p>\n<p>  function clearCart() {<br \/>\n    items.value &#061; []<br \/>\n  }<\/p>\n<p>  \/\/ \u5f02\u6b65\u65b9\u6cd5<br \/>\n  async function checkout() {<br \/>\n    if (isEmpty.value) {<br \/>\n      throw new Error(&#039;\u8d2d\u7269\u8f66\u4e3a\u7a7a&#039;)<br \/>\n    }<\/p>\n<p>    isLoading.value &#061; true<br \/>\n    try {<br \/>\n      \/\/ \u6a21\u62dfAPI\u8c03\u7528<br \/>\n      await new Promise(resolve &#061;&gt; setTimeout(resolve, 2000))<\/p>\n<p>      \/\/ \u6e05\u7a7a\u8d2d\u7269\u8f66<br \/>\n      clearCart()<\/p>\n<p>      return { success: true, message: &#039;\u8ba2\u5355\u63d0\u4ea4\u6210\u529f&#xff01;&#039; }<br \/>\n    } catch (error) {<br \/>\n      throw new Error(&#039;\u8ba2\u5355\u63d0\u4ea4\u5931\u8d25&#xff1a;&#039; &#043; error.message)<br \/>\n    } finally {<br \/>\n      isLoading.value &#061; false<br \/>\n    }<br \/>\n  }<\/p>\n<p>  \/\/ \u6301\u4e45\u5316<br \/>\n  function saveToLocalStorage() {<br \/>\n    localStorage.setItem(&#039;cart&#039;, JSON.stringify(items.value))<br \/>\n  }<\/p>\n<p>  function loadFromLocalStorage() {<br \/>\n    const saved &#061; localStorage.getItem(&#039;cart&#039;)<br \/>\n    if (saved) {<br \/>\n      items.value &#061; JSON.parse(saved)<br \/>\n    }<br \/>\n  }<\/p>\n<p>  return {<br \/>\n    \/\/ \u72b6\u6001<br \/>\n    items,<br \/>\n    isLoading,<br \/>\n    \/\/ \u8ba1\u7b97\u5c5e\u6027<br \/>\n    totalItems,<br \/>\n    totalPrice,<br \/>\n    isEmpty,<br \/>\n    itemCount,<br \/>\n    \/\/ \u65b9\u6cd5<br \/>\n    addItem,<br \/>\n    removeItem,<br \/>\n    updateQuantity,<br \/>\n    clearCart,<br \/>\n    checkout,<br \/>\n    saveToLocalStorage,<br \/>\n    loadFromLocalStorage<br \/>\n  }<br \/>\n})<\/p>\n<h5 id=\"\u4ea7\u54c1store\u793a\u4f8b\">\u4ea7\u54c1Store\u793a\u4f8b<\/h5>\n<p>\/\/ stores\/products.js<br \/>\nimport { defineStore } from &#039;pinia&#039;<br \/>\nimport { ref, computed } from &#039;vue&#039;<\/p>\n<p>export const useProductsStore &#061; defineStore(&#039;products&#039;, () &#061;&gt; {<br \/>\n  \/\/ \u72b6\u6001<br \/>\n  const products &#061; ref([])<br \/>\n  const categories &#061; ref([])<br \/>\n  const loading &#061; ref(false)<br \/>\n  const error &#061; ref(null)<br \/>\n  const filters &#061; ref({<br \/>\n    category: &#039;&#039;,<br \/>\n    search: &#039;&#039;,<br \/>\n    sortBy: &#039;name&#039;,<br \/>\n    sortOrder: &#039;asc&#039;<br \/>\n  })<\/p>\n<p>  \/\/ \u8ba1\u7b97\u5c5e\u6027<br \/>\n  const filteredProducts &#061; computed(() &#061;&gt; {<br \/>\n    let filtered &#061; products.value<\/p>\n<p>    \/\/ \u6309\u5206\u7c7b\u7b5b\u9009<br \/>\n    if (filters.value.category) {<br \/>\n      filtered &#061; filtered.filter(product &#061;&gt;<br \/>\n        product.category &#061;&#061;&#061; filters.value.category<br \/>\n      )<br \/>\n    }<\/p>\n<p>    \/\/ \u6309\u641c\u7d22\u8bcd\u7b5b\u9009<br \/>\n    if (filters.value.search) {<br \/>\n      const searchLower &#061; filters.value.search.toLowerCase()<br \/>\n      filtered &#061; filtered.filter(product &#061;&gt;<br \/>\n        product.name.toLowerCase().includes(searchLower) ||<br \/>\n        product.description.toLowerCase().includes(searchLower)<br \/>\n      )<br \/>\n    }<\/p>\n<p>    \/\/ \u6392\u5e8f<br \/>\n    filtered.sort((a, b) &#061;&gt; {<br \/>\n      const aValue &#061; a[filters.value.sortBy]<br \/>\n      const bValue &#061; b[filters.value.sortBy]<\/p>\n<p>      if (filters.value.sortOrder &#061;&#061;&#061; &#039;asc&#039;) {<br \/>\n        return aValue &gt; bValue ? 1 : -1<br \/>\n      } else {<br \/>\n        return aValue &lt; bValue ? 1 : -1<br \/>\n      }<br \/>\n    })<\/p>\n<p>    return filtered<br \/>\n  })<\/p>\n<p>  const availableCategories &#061; computed(() &#061;&gt; {<br \/>\n    return [&#8230;new Set(products.value.map(p &#061;&gt; p.category))]<br \/>\n  })<\/p>\n<p>  \/\/ \u65b9\u6cd5<br \/>\n  async function fetchProducts() {<br \/>\n    loading.value &#061; true<br \/>\n    error.value &#061; null<\/p>\n<p>    try {<br \/>\n      \/\/ \u6a21\u62dfAPI\u8c03\u7528<br \/>\n      await new Promise(resolve &#061;&gt; setTimeout(resolve, 1000))<\/p>\n<p>      \/\/ \u6a21\u62df\u4ea7\u54c1\u6570\u636e<br \/>\n      products.value &#061; [<br \/>\n        { id: 1, name: &#039;Vue3\u6559\u7a0b&#039;, price: 99, category: &#039;\u6559\u80b2&#039;, description: &#039;Vue3\u5b8c\u6574\u5b66\u4e60\u6559\u7a0b&#039; },<br \/>\n        { id: 2, name: &#039;React\u6559\u7a0b&#039;, price: 88, category: &#039;\u6559\u80b2&#039;, description: &#039;React\u5f00\u53d1\u6307\u5357&#039; },<br \/>\n        { id: 3, name: &#039;TypeScript\u6559\u7a0b&#039;, price: 77, category: &#039;\u6559\u80b2&#039;, description: &#039;TypeScript\u5165\u95e8&#039; },<br \/>\n        { id: 4, name: &#039;Node.js\u6559\u7a0b&#039;, price: 66, category: &#039;\u6559\u80b2&#039;, description: &#039;Node.js\u540e\u7aef\u5f00\u53d1&#039; },<br \/>\n        { id: 5, name: &#039;Python\u6559\u7a0b&#039;, price: 55, category: &#039;\u6559\u80b2&#039;, description: &#039;Python\u7f16\u7a0b\u57fa\u7840&#039; },<br \/>\n        { id: 6, name: &#039;Java\u6559\u7a0b&#039;, price: 44, category: &#039;\u6559\u80b2&#039;, description: &#039;Java\u4f01\u4e1a\u7ea7\u5f00\u53d1&#039; }<br \/>\n      ]<br \/>\n    } catch (err) {<br \/>\n      error.value &#061; err.message<br \/>\n    } finally {<br \/>\n      loading.value &#061; false<br \/>\n    }<br \/>\n  }<\/p>\n<p>  function setFilter(key, value) {<br \/>\n    filters.value[key] &#061; value<br \/>\n  }<\/p>\n<p>  function clearFilters() {<br \/>\n    filters.value &#061; {<br \/>\n      category: &#039;&#039;,<br \/>\n      search: &#039;&#039;,<br \/>\n      sortBy: &#039;name&#039;,<br \/>\n      sortOrder: &#039;asc&#039;<br \/>\n    }<br \/>\n  }<\/p>\n<p>  function getProductById(id) {<br \/>\n    return products.value.find(product &#061;&gt; product.id &#061;&#061;&#061; id)<br \/>\n  }<\/p>\n<p>  return {<br \/>\n    \/\/ \u72b6\u6001<br \/>\n    products,<br \/>\n    categories,<br \/>\n    loading,<br \/>\n    error,<br \/>\n    filters,<br \/>\n    \/\/ \u8ba1\u7b97\u5c5e\u6027<br \/>\n    filteredProducts,<br \/>\n    availableCategories,<br \/>\n    \/\/ \u65b9\u6cd5<br \/>\n    fetchProducts,<br \/>\n    setFilter,<br \/>\n    clearFilters,<br \/>\n    getProductById<br \/>\n  }<br \/>\n})<\/p>\n<h2 id=\"-\u672c\u7ae0\u5c0f\u7ed3\">\u5c0f\u7ed3<\/h2>\n<h4 id=\"\u5b66\u4e60\u8981\u70b9\u56de\u987e\">\u5b66\u4e60\u8981\u70b9\u56de\u987e<\/h4>\n<li>Pinia\u57fa\u7840&#xff1a;Store\u7684\u5b9a\u4e49\u548c\u521b\u5efa&#xff0c;\u7ec4\u5408\u5f0fAPI\u98ce\u683c<\/li>\n<li>\u72b6\u6001\u7ba1\u7406&#xff1a;\u72b6\u6001\u3001\u8ba1\u7b97\u5c5e\u6027\u3001\u65b9\u6cd5\u7684\u7ec4\u7ec7\u548c\u4f7f\u7528<\/li>\n<li>Store\u7ec4\u5408&#xff1a;\u591a\u4e2aStore\u7684\u534f\u4f5c\u548c\u7ec4\u5408<\/li>\n<li>\u5b9e\u9645\u5e94\u7528&#xff1a;\u8d2d\u7269\u8f66\u3001\u7528\u6237\u7ba1\u7406\u7b49\u5b9e\u9645\u573a\u666f<\/li><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6587\u7ae0\u6d4f\u89c8\u9605\u8bfb93\u6b21\u3002Pinia\u662fVue3\u7684\u5b98\u65b9\u72b6\u6001\u7ba1\u7406\u5e93\uff0c\u5b83\u63d0\u4f9b\u4e86\u7b80\u5355\u3001\u76f4\u89c2\u7684\u72b6\u6001\u7ba1\u7406\u89e3\u51b3\u65b9\u6848\uff0c\u4e0eVue3\u7684Composition API\u5b8c\u7f8e\u96c6\u6210\u3002\/\/ \u72b6\u6001\/\/ \u8ba1\u7b97\u5c5e\u6027\/\/ \u65b9\u6cd5\/\/ \u5f02\u6b65\u65b9\u6cd5return {\/\/ \u72b6\u6001count,name,\/\/ \u8ba1\u7b97\u5c5e\u6027isEven,\/\/ \u65b9\u6cd5increment,decrement,reset,setCount,})<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[187,625,87],"topic":[],"class_list":["post-55188","post","type-post","status-publish","format-standard","hentry","category-server","tag-javascript","tag-vue-js","tag-87"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/55188.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u6587\u7ae0\u6d4f\u89c8\u9605\u8bfb93\u6b21\u3002Pinia\u662fVue3\u7684\u5b98\u65b9\u72b6\u6001\u7ba1\u7406\u5e93\uff0c\u5b83\u63d0\u4f9b\u4e86\u7b80\u5355\u3001\u76f4\u89c2\u7684\u72b6\u6001\u7ba1\u7406\u89e3\u51b3\u65b9\u6848\uff0c\u4e0eVue3\u7684Composition API\u5b8c\u7f8e\u96c6\u6210\u3002\/\/ \u72b6\u6001\/\/ \u8ba1\u7b97\u5c5e\u6027\/\/ \u65b9\u6cd5\/\/ \u5f02\u6b65\u65b9\u6cd5return {\/\/ \u72b6\u6001count,name,\/\/ \u8ba1\u7b97\u5c5e\u6027isEven,\/\/ \u65b9\u6cd5increment,decrement,reset,setCount,})\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/55188.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2025-08-13T10:54:38+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/55188.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/55188.html\",\"name\":\"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2025-08-13T10:54:38+00:00\",\"dateModified\":\"2025-08-13T10:54:38+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/55188.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/55188.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/55188.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/55188.html","og_locale":"zh_CN","og_type":"article","og_title":"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u6587\u7ae0\u6d4f\u89c8\u9605\u8bfb93\u6b21\u3002Pinia\u662fVue3\u7684\u5b98\u65b9\u72b6\u6001\u7ba1\u7406\u5e93\uff0c\u5b83\u63d0\u4f9b\u4e86\u7b80\u5355\u3001\u76f4\u89c2\u7684\u72b6\u6001\u7ba1\u7406\u89e3\u51b3\u65b9\u6848\uff0c\u4e0eVue3\u7684Composition API\u5b8c\u7f8e\u96c6\u6210\u3002\/\/ \u72b6\u6001\/\/ \u8ba1\u7b97\u5c5e\u6027\/\/ \u65b9\u6cd5\/\/ \u5f02\u6b65\u65b9\u6cd5return {\/\/ \u72b6\u6001count,name,\/\/ \u8ba1\u7b97\u5c5e\u6027isEven,\/\/ \u65b9\u6cd5increment,decrement,reset,setCount,})","og_url":"https:\/\/www.wsisp.com\/helps\/55188.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2025-08-13T10:54:38+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"6 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/55188.html","url":"https:\/\/www.wsisp.com\/helps\/55188.html","name":"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2025-08-13T10:54:38+00:00","dateModified":"2025-08-13T10:54:38+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/55188.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/55188.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/55188.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"(Vue3\u5165\u95e8\u6559\u7a0b)Vue3\u72b6\u6001\u7ba1\u7406Pinia\u7528\u6cd5\u8be6\u89e3"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/55188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=55188"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/55188\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=55188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=55188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=55188"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=55188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}