]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
docs: add rulekit v3
authorEduardo San Martin Morote <posva13@gmail.com>
Thu, 3 Jul 2025 19:38:38 +0000 (21:38 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Thu, 3 Jul 2025 19:38:38 +0000 (21:38 +0200)
45 files changed:
packages/docs/.vitepress/theme/components/RuleKitLink.vue [new file with mode: 0644]
packages/docs/.vitepress/theme/index.ts
packages/docs/.vitepress/theme/styles/home-links.css
packages/docs/cookbook/composables.md
packages/docs/cookbook/composing-stores.md
packages/docs/cookbook/hot-module-replacement.md
packages/docs/cookbook/index.md
packages/docs/cookbook/migration-v1-v2.md
packages/docs/cookbook/migration-v2-v3.md
packages/docs/cookbook/migration-vuex.md
packages/docs/cookbook/options-api.md
packages/docs/cookbook/testing.md
packages/docs/cookbook/vscode-snippets.md
packages/docs/core-concepts/actions.md
packages/docs/core-concepts/getters.md
packages/docs/core-concepts/index.md
packages/docs/core-concepts/outside-component-usage.md
packages/docs/core-concepts/plugins.md
packages/docs/core-concepts/state.md
packages/docs/getting-started.md
packages/docs/index.md
packages/docs/introduction.md
packages/docs/public/rulekit-logo.svg [new file with mode: 0644]
packages/docs/ssr/index.md
packages/docs/ssr/nuxt.md
packages/docs/zh/cookbook/composables.md
packages/docs/zh/cookbook/composing-stores.md
packages/docs/zh/cookbook/hot-module-replacement.md
packages/docs/zh/cookbook/index.md
packages/docs/zh/cookbook/migration-v1-v2.md
packages/docs/zh/cookbook/migration-vuex.md
packages/docs/zh/cookbook/options-api.md
packages/docs/zh/cookbook/testing.md
packages/docs/zh/cookbook/vscode-snippets.md
packages/docs/zh/core-concepts/actions.md
packages/docs/zh/core-concepts/getters.md
packages/docs/zh/core-concepts/index.md
packages/docs/zh/core-concepts/outside-component-usage.md
packages/docs/zh/core-concepts/plugins.md
packages/docs/zh/core-concepts/state.md
packages/docs/zh/getting-started.md
packages/docs/zh/index.md
packages/docs/zh/introduction.md
packages/docs/zh/ssr/index.md
packages/docs/zh/ssr/nuxt.md

diff --git a/packages/docs/.vitepress/theme/components/RuleKitLink.vue b/packages/docs/.vitepress/theme/components/RuleKitLink.vue
new file mode 100644 (file)
index 0000000..ff52d35
--- /dev/null
@@ -0,0 +1,206 @@
+<script setup lang="ts">
+import { useData } from 'vitepress'
+
+const { site } = useData()
+
+const translations = {
+  'en-US': 'Vibe code Vue apps with confidence',
+  'zh-CN': '自信地编写 Vue 应用的 Vibe 代码',
+}
+</script>
+
+<template>
+  <div class="rulekit">
+    <a
+      href="https://rulekit.dev?from=vuerouter"
+      target="_blank"
+      rel="sponsored noopener"
+      aria-label="Visit RuleKit - curated rules for Cursor, Claude Code, and more (opens in new tab)"
+      class="rulekit-link"
+    >
+      <div class="rulekit-content">
+        <div class="rulekit-left">
+          <span class="rulekit-sparkles" aria-hidden="true">✨</span>
+          <span class="rulekit-text">
+            <slot>{{ translations[site.lang] || translations['en-US'] }}</slot>
+          </span>
+        </div>
+        <div class="rulekit-right">
+          <svg
+            width="1024"
+            height="1024"
+            viewBox="0 0 1024 1024"
+            fill="none"
+            xmlns="http://www.w3.org/2000/svg"
+            role="img"
+            alt="RuleKit logo"
+            class="rulekit-logo"
+          >
+            <path
+              d="M335 694L353.947 697.225V737L335 733.775V694Z"
+              fill="currentColor"
+            />
+            <path
+              d="M355 538.234V673L335 669.766V536.078L355 538.234Z"
+              fill="currentColor"
+            />
+            <path
+              d="M259.255 329.5L313.424 338.585V414.78L374.576 425.512V350.39L422.5 359.457L422.529 391.816L399.251 388.374V443.756L375.649 440.537V460.314L313.424 449.576V430.878L287.675 426.585L286.602 367.561L259.255 364V329.5Z"
+              fill="currentColor"
+            />
+            <path
+              d="M398.897 113.5L647.031 158.597V199L676.034 205.5V276L836.085 304.623L896.239 362.605V498.968L873.681 516.147V778.5L914.5 792.095L755.522 914.5L180.84 802.832L130.354 738.409V472.125L103.5 457.092V336.835L164.728 270.264L291.48 205.5L321.557 211V176.85L350.56 165.5V139L398.897 113.5ZM379.562 148.933V184L350.56 182.218L349.485 259.527L379.562 263.822V184L582.581 218.725V300.328L622.325 307V224.094L598.693 220.873V188.661L379.562 148.933ZM433.271 218.725V234.831L561.097 257.379V240.2L433.271 218.725ZM291.48 234.831L223.807 272.412L740.484 364.752L802.786 325.024L673.885 302.476L622.325 330L561.097 319V282L433.271 259.527L389.23 285.296L321.557 275V240.2L291.48 234.831ZM180.84 288.517L128.206 343.277V440.537L233.475 461.387L232.401 360.457L259.255 364V446L284.103 449.576V476.42L311.889 480.714V750L373.117 762L374.191 691.165V493.599L399.251 497V472.125L422.5 476.42L422.529 391.816L449.383 396.964V500L543.911 516V414.143L571.839 418.438V388.374L624.474 396.964V423.807L652.402 428V534.5L778.08 551.5V443.756L731 392.244L180.84 288.517ZM831.789 336.835L757.671 383.005L796.341 423.807L871.533 374.416L831.789 336.835ZM807.083 445.281V529.032L871.533 486.083V404.48L807.083 445.281ZM571.839 449.576V521.516L587 524.5V592L606.213 595.603V527.5L624.474 531V458.5L571.839 449.576ZM155.06 472.125V729.5L191.5 778.5L713 880.5L754.448 853.298V579.497L635.215 560.17V601L682.479 609.562V649.29L663.144 647V682.575L682.479 684.723L683.5 814.5L652.402 808.201V839L543.911 819.5V788.874L511.685 783.505V654.5L532.095 658.5V623.52L511.685 620.299V578.424L557.875 585.94V545.138L422.5 521.516L402.12 538.234V654.658V766.326L373.117 762V791.021L311.889 778.5V750L285.035 744.851V512.926L264.5 493.599L155.06 472.125ZM778.08 579.497L780.228 833.971L847.901 781.358V538.234L778.08 579.497ZM561.097 627.5V664.5L543.911 661V788.874L565.394 793.169L567 669L584.729 672V632.5L561.097 627.5ZM611.583 639.626V676.5L628.77 679V802.832L652.402 808.201V682.575L635.215 680.428V643L611.583 639.626Z"
+              fill="currentColor"
+            />
+          </svg>
+          <span class="rulekit-title">RuleKit</span>
+        </div>
+      </div>
+    </a>
+  </div>
+</template>
+
+<style scoped>
+.rulekit {
+  margin: 1rem 0;
+}
+
+.rulekit-title {
+  font-family:
+    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
+    'Liberation Mono', 'Courier New', monospace;
+}
+
+.rulekit-link {
+  display: block;
+  padding: 1rem 1.5rem;
+  border-radius: 12px;
+  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
+  border: 1px solid #dee2e6;
+  text-decoration: none;
+  color: #212529;
+  transition: all 0.3s ease;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+  position: relative;
+  overflow: hidden;
+}
+
+.rulekit-link:visited {
+  color: #212529;
+}
+
+.rulekit-link:focus {
+  outline: 2px solid #0066cc;
+  outline-offset: 2px;
+}
+
+.rulekit-link:focus:not(:focus-visible) {
+  outline: none;
+}
+
+.rulekit-link::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: -100%;
+  width: 100%;
+  height: 100%;
+  background: linear-gradient(
+    90deg,
+    transparent,
+    rgba(255, 255, 255, 0.4),
+    transparent
+  );
+  transition: left 0.6s ease;
+}
+
+.rulekit-link:hover::before {
+  left: 100%;
+}
+
+.rulekit-link:hover {
+  text-decoration: none !important;
+  transform: translateY(-2px);
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
+  background: linear-gradient(135deg, #f1f3f4 0%, #e2e6ea 100%);
+}
+
+.rulekit-content {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 1rem;
+  position: relative;
+  z-index: 2;
+}
+
+.rulekit-left {
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+}
+
+.rulekit-right {
+  display: flex;
+  align-items: center;
+  gap: 0.5rem;
+}
+
+.rulekit-sparkles {
+  font-size: 1.5rem;
+}
+
+.rulekit-logo {
+  width: 2rem;
+  height: 2rem;
+  flex-shrink: 0;
+  color: #495057;
+}
+
+.rulekit-text {
+  font-weight: 500;
+  font-family:
+    'Spectral', ui-serif, system-ui, sans-serif, 'Apple Color Emoji',
+    'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+  font-size: 0.95rem;
+  line-height: 1.4;
+}
+
+/* Dark mode styles */
+.dark .rulekit-link {
+  background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
+  border-color: #404040;
+  color: #e5e5e5;
+}
+
+.dark .rulekit-link::before {
+  background: linear-gradient(
+    90deg,
+    transparent,
+    rgba(255, 255, 255, 0.15),
+    transparent
+  );
+}
+
+.dark .rulekit-link:hover {
+  text-decoration: none !important;
+  background: linear-gradient(135deg, #262626 0%, #363636 100%);
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
+}
+
+.dark .rulekit-logo {
+  color: #ffffff;
+}
+
+.dark .rulekit-text {
+  color: #e5e5e5;
+}
+
+.dark .rulekit-link:visited {
+  color: #e5e5e5;
+}
+
+.dark .rulekit-link:focus {
+  outline-color: #66b3ff;
+}
+</style>
index a205ef1409ab0a5beba01ea0f0dd414ca7d4cf24..f67f0606507992da1b1c7c8dc3732cb5df2286e7 100644 (file)
@@ -11,6 +11,7 @@ import './styles/playground-links.css'
 import VueSchoolLink from './components/VueSchoolLink.vue'
 import VueMasteryLogoLink from './components/VueMasteryLogoLink.vue'
 import MasteringPiniaLink from './components/MasteringPiniaLink.vue'
+import RuleKitLink from './components/RuleKitLink.vue'
 import status from '../translation-status.json'
 
 const i18nLabels = {
@@ -33,6 +34,7 @@ const theme: Theme = {
     app.component('VueSchoolLink', VueSchoolLink)
     app.component('VueMasteryLogoLink', VueMasteryLogoLink)
     app.component('MasteringPiniaLink', MasteringPiniaLink)
+    app.component('RuleKitLink', RuleKitLink)
   },
 }
 
index 108987faced01d203b01ec381e015eaf3259bbb6..b1702c1e85d597ed1e4fa8e18ee4d76e17a22b43 100644 (file)
@@ -99,6 +99,28 @@ a.cta.vueschool::after {
   border-left: 7px solid currentColor;
 }
 
+a.cta.rulekit {
+  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
+}
+
+a.cta.rulekit::before {
+  content: '';
+  display: inline-block;
+  width: 16px;
+  height: 16px;
+  background-image: url('/rulekit-logo.svg');
+  background-size: 16px;
+  background-repeat: no-repeat;
+  background-position: center;
+  margin-right: 0.5em;
+  vertical-align: middle;
+  filter: brightness(0); /* Make it black by default */
+}
+
+html.dark a.cta.rulekit::before {
+  filter: brightness(0) invert(1); /* Make it white in dark mode */
+}
+
 @media (max-width: 420px) {
   a.cta.cta.vue-mastery {
     max-width: 320px;
index ab655fe157d64a07e69607642c4c6181ac1eac0b..6ace86e4e6cdd17bba31caa2372432050d70763b 100644 (file)
@@ -21,6 +21,8 @@ export const useAuthStore = defineStore('auth', {
 
 Keep in mind that **you can only return writable state** (e.g. a `ref()`). Here are some examples of composables that you can use:
 
+<RuleKitLink />
+
 - [useLocalStorage](https://vueuse.org/core/useLocalStorage/)
 - [useAsyncState](https://vueuse.org/core/useAsyncState/)
 
index 44894f8df9976ca17d6c7e509c697f05580a3191..de89b99b0378426131dbcc2b2fbf98b9859c3f9e 100644 (file)
@@ -1,5 +1,7 @@
 # Composing Stores
 
+<RuleKitLink />
+
 Composing stores is about having stores that use each other, and this is supported in Pinia. There is one rule to follow:
 
 If **two or more stores use each other**, they cannot create an infinite loop through _getters_ or _actions_. They cannot **both** directly read each other state in their setup function:
index af5d6bd5faa08861c966bc3c3db76dc8b6349171..3ec95340a3f690d6e4da5a30e1254b56f5e8ab2d 100644 (file)
@@ -1,5 +1,7 @@
 # HMR (Hot Module Replacement)
 
+<RuleKitLink />
+
 Pinia supports Hot Module replacement so you can edit your stores and interact with them directly in your app without reloading the page, allowing you to keep the existing state, add, or even remove state, actions, and getters.
 
 At the moment, only [Vite](https://vitejs.dev/guide/api-hmr.html#hmr-api) is officially supported but any bundler implementing the `import.meta.hot` spec should work (e.g. [webpack](https://webpack.js.org/api/module-variables/#importmetawebpackhot) seems to use `import.meta.webpackHot` instead of `import.meta.hot`). 
index 0bdf9a5e366e9254144f506ebc8ed27c61f38b3b..5bad5194b8f03b4c78137ba662743f5c95ffe0f3 100644 (file)
@@ -1,5 +1,7 @@
 # Cookbook
 
+<RuleKitLink />
+
 - [Migrating from Vuex ≤4](./migration-vuex.md): A migration guide for converting Vuex ≤4 projects.
 - [HMR](./hot-module-replacement.md): How to activate hot module replacement and improve the developer experience.
 - [Testing Stores (WIP)](./testing.md): How to unit test Stores and mock them in component unit tests.
index 457969fa7697822501ba2e7ac1b0aa573a00d0ac..e502fbacf8f57468fd3ef6cff51d85abf1777420 100644 (file)
@@ -1,5 +1,7 @@
 # Migrating from 0.x (v1) to v2
 
+<RuleKitLink />
+
 Starting at version `2.0.0-rc.4`, pinia supports both Vue 2 and Vue 3! This means, all new updates will be applied to this version 2 so both Vue 2 and Vue 3 users can benefit from it. If you are using Vue 3, this doesn't change anything for you as you were already using the rc and you can check [the CHANGELOG](https://github.com/vuejs/pinia/blob/v2/packages/pinia/CHANGELOG.md) for a detailed explanation of everything that changed. Otherwise, **this guide is for you**!
 
 ## Deprecations
index 3f244874b6cbaa22cd1f8179571560b18e992b0c..d347bc61a70461929039c4db9b9c7ad62a631d28 100644 (file)
@@ -1,5 +1,7 @@
 # Migrating from v2 to v3
 
+<RuleKitLink />
+
 Pinia v3 is a _boring_ major release with no new features. It drops deprecated APIs and updates major dependencies. It only supports Vue 3. If you are using Vue 2, you can keep using v2. If you need help, [book help with Pinia's author](https://cal.com/posva/consultancy).
 
 For most users, the migration should require **no change**. This guide is here to help you in case you encounter any issues.
index a388652c770540f4abfeeb83ece98fe1da839315..5919dc21749a1a4c265c75216dba558cd6fe4828 100644 (file)
@@ -14,6 +14,8 @@ The easiest way to transition that concept to be used with Pinia is that each mo
 
 How you choose to restructure your Vuex modules into Pinia stores is entirely up to you, but here is one suggestion:
 
+<RuleKitLink />
+
 ```bash
 # Vuex example (assuming namespaced modules)
 src
index 6c352f725691c42945a7a8e6deee4b4963d28a2a..20d704682b4512ac5bda9196d0c2822922b306a8 100644 (file)
@@ -8,6 +8,8 @@ Pinia can be used even if you are not using the composition API (if you are usin
 - ⚠️ [mapGetters](../core-concepts/getters.md#without-setup) (just for migration convenience, use `mapState()` instead)
 - [mapActions](../core-concepts/actions.md#without-setup)
 
+<RuleKitLink />
+
 ## Giving access to the whole store
 
 If you need to access pretty much everything from the store, it might be too much to map every single property of the store... Instead you can get access to the whole store with `mapStores()`:
index 3eab75d9496f51f8bd118c310ece6c0e8a7d9879..4c1a2a0f5474b9802ee93c195fdb2802e8610234 100644 (file)
@@ -13,6 +13,8 @@ Stores will, by design, be used at many places and can make testing much harder
 
 Depending on what or how you are testing, we need to take care of these three things differently.
 
+<RuleKitLink />
+
 ## Unit testing a store
 
 To unit test a store, the most important part is creating a `pinia` instance:
index 18331952a2f58ca29e6404ecf265daafc09b1be9..334f0f297bc7461ef9ff9c46be147729ae99cd6a 100644 (file)
@@ -1,5 +1,7 @@
 # VS Code Snippets
 
+<RuleKitLink />
+
 These are some snippets that I use in VS Code to make my life easier.
 
 Manage user snippets with <kbd>⇧ Shift</kbd>+<kbd>⌘ Command</kbd>+<kbd>P</kbd> / <kbd>⇧ Shift</kbd>+<kbd>⌃ Control</kbd>+<kbd>P</kbd> and then `Snippets: Configure User Snippets`.
index c795219b5abf3cf159d6eaafb14e3b497a094301..a15b9218e0124fa0d3cd09c63f33fec8d9ae5e5b 100644 (file)
@@ -29,6 +29,8 @@ export const useCounterStore = defineStore('counter', {
 })
 ```
 
+<RuleKitLink />
+
 Like [getters](./getters.md), actions get access to the _whole store instance_ through `this` with **full typing (and autocompletion ✨) support**. **Unlike getters, `actions` can be asynchronous**, you can `await` inside of actions any API call or even other actions! Here is an example using [Mande](https://github.com/posva/mande). Note the library you use doesn't matter as long as you get a `Promise`. You could even use the native `fetch` function (browser only):
 
 ```js
index 4942c7baa22df49afdc844656d50854c28dec4dc..f1a9fc1036b574f476720577ae3380a0b0b93129 100644 (file)
@@ -23,6 +23,8 @@ export const useCounterStore = defineStore('counter', {
 })
 ```
 
+<RuleKitLink />
+
 Most of the time, getters will only rely on the state. However, they might need to use other getters. Because of this, we can get access to the _whole store instance_ through `this` when defining a regular function **but it is necessary to define the type of the return type (in TypeScript)**. This is due to a known limitation in TypeScript and **doesn't affect getters defined with an arrow function nor getters not using `this`**:
 
 ```ts
index 49c2350c1962ae66668fa38f8709f84593296b3e..f3cc3eee92e0f8a011491d657be6fb12b61c6efb 100644 (file)
@@ -29,6 +29,8 @@ This _name_, also referred to as _id_, is necessary and is used by Pinia to conn
 
 `defineStore()` accepts two distinct values for its second argument: a Setup function or an Options object.
 
+<RuleKitLink />
+
 ## Option Stores
 
 Similar to Vue's Options API, we can also pass an Options Object with `state`, `actions`, and `getters` properties.
index 97ddc53e55df4b3d604f3202e582e37b3a948ea7..97bb7ee86184c2c99d2a049aaa733360537b5c30 100644 (file)
@@ -10,6 +10,8 @@ Pinia stores rely on the `pinia` instance to share the same store instance acros
 Behind the scenes, `useStore()` _injects_ the `pinia` instance you gave to your `app`. This means that if the `pinia` instance cannot be automatically injected, you have to manually provide it to the `useStore()` function.
 You can solve this differently depending on the kind of application you are writing.
 
+<RuleKitLink />
+
 ## Single Page Applications
 
 If you are not doing any SSR (Server Side Rendering), any call of `useStore()` after installing the pinia plugin with `app.use(pinia)` will work:
index 02379bd3ff13e06ae0ea2c0d6acc8901813c84cb..3ecff4d0c2ad2468366edd6624d558099cd9295b 100644 (file)
@@ -15,6 +15,8 @@ Pinia stores can be fully extended thanks to a low level API. Here is a list of
 - Implement side effects like [Local Storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)
 - Apply **only** to specific stores
 
+<RuleKitLink />
+
 Plugins are added to the pinia instance with `pinia.use()`. The simplest example is adding a static property to all stores by returning an object:
 
 ```js
index a0bacc5a3d6b64d23d91386a8d1a929c3ce54aad..4421f770ccc946fcca2e7776132f166a2c9fe2d3 100644 (file)
@@ -36,6 +36,8 @@ In order for Vue to properly detect state, you must declare every state piece in
 
 :::
 
+<RuleKitLink />
+
 ## TypeScript
 
 You don't need to do much in order to make your state compatible with TS: make sure [`strict`](https://www.typescriptlang.org/tsconfig#strict), or at the very least, [`noImplicitThis`](https://www.typescriptlang.org/tsconfig#noImplicitThis), is enabled and Pinia will infer the type of your state automatically! However, there are a few cases where you should give it a hand with some casting:
index 57566cf6aa3ef7f28ab14a61df76c89d7e4cc926..251972340e9f12a0541d6e92e58d78da0428ba51 100644 (file)
@@ -52,6 +52,8 @@ app.mount('#app')
 
 A Store (like Pinia) is an entity holding state and business logic that isn't bound to your Component tree. In other words, **it hosts global state**. It's a bit like a component that is always there and that everybody can read off and write to. It has **three concepts**, the [state](./core-concepts/state.md), [getters](./core-concepts/getters.md) and [actions](./core-concepts/actions.md) and it's safe to assume these concepts are the equivalent of `data`, `computed` and `methods` in components.
 
+<RuleKitLink />
+
 ## When should I use a Store
 
 A store should contain data that can be accessed throughout your application. This includes data that is used in many places, e.g. User information that is displayed in the navbar, as well as data that needs to be preserved through pages, e.g. a very complicated multi-step form.
index 4661bf0b4597507cf587a25b584d6309ffdd9280..a7f8fbc7a9a239e64068abe8a4f3fdc823ebb33a 100644 (file)
@@ -18,6 +18,9 @@ hero:
     - theme: alt
       text: Demo
       link: https://stackblitz.com/github/piniajs/example-vue-3-vite
+    - theme: cta rulekit
+      text: RuleKit
+      link: https://rulekit.dev?from=vuerouter
     - theme: cta mastering-pinia
       text: ' '
       link: https://masteringpinia.com
index 7092e98ca70ef8c23de17919878ecb809d5bb7d9..902948b1196f6583e870d7a3bda73ecca85b3843 100644 (file)
@@ -35,6 +35,8 @@ Pinia is a store library for Vue, it allows you to share a state across componen
 
 If you still have doubts, check out [the **official** Mastering Pinia course](https://masteringpinia.com). In the beginning we cover how to build our own `defineStore()` function and then we move to the official Pinia API.
 
+<RuleKitLink />
+
 <VueMasteryLogoLink for="pinia-cheat-sheet">
 </VueMasteryLogoLink>
 
diff --git a/packages/docs/public/rulekit-logo.svg b/packages/docs/public/rulekit-logo.svg
new file mode 100644 (file)
index 0000000..f20d617
--- /dev/null
@@ -0,0 +1,6 @@
+<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <path d="M335 694L353.947 697.225V737L335 733.775V694Z" fill="currentColor"/>
+  <path d="M355 538.234V673L335 669.766V536.078L355 538.234Z" fill="currentColor"/>
+  <path d="M259.255 329.5L313.424 338.585V414.78L374.576 425.512V350.39L422.5 359.457L422.529 391.816L399.251 388.374V443.756L375.649 440.537V460.314L313.424 449.576V430.878L287.675 426.585L286.602 367.561L259.255 364V329.5Z" fill="currentColor"/>
+  <path d="M398.897 113.5L647.031 158.597V199L676.034 205.5V276L836.085 304.623L896.239 362.605V498.968L873.681 516.147V778.5L914.5 792.095L755.522 914.5L180.84 802.832L130.354 738.409V472.125L103.5 457.092V336.835L164.728 270.264L291.48 205.5L321.557 211V176.85L350.56 165.5V139L398.897 113.5ZM379.562 148.933V184L350.56 182.218L349.485 259.527L379.562 263.822V184L582.581 218.725V300.328L622.325 307V224.094L598.693 220.873V188.661L379.562 148.933ZM433.271 218.725V234.831L561.097 257.379V240.2L433.271 218.725ZM291.48 234.831L223.807 272.412L740.484 364.752L802.786 325.024L673.885 302.476L622.325 330L561.097 319V282L433.271 259.527L389.23 285.296L321.557 275V240.2L291.48 234.831ZM180.84 288.517L128.206 343.277V440.537L233.475 461.387L232.401 360.457L259.255 364V446L284.103 449.576V476.42L311.889 480.714V750L373.117 762L374.191 691.165V493.599L399.251 497V472.125L422.5 476.42L422.529 391.816L449.383 396.964V500L543.911 516V414.143L571.839 418.438V388.374L624.474 396.964V423.807L652.402 428V534.5L778.08 551.5V443.756L731 392.244L180.84 288.517ZM831.789 336.835L757.671 383.005L796.341 423.807L871.533 374.416L831.789 336.835ZM807.083 445.281V529.032L871.533 486.083V404.48L807.083 445.281ZM571.839 449.576V521.516L587 524.5V592L606.213 595.603V527.5L624.474 531V458.5L571.839 449.576ZM155.06 472.125V729.5L191.5 778.5L713 880.5L754.448 853.298V579.497L635.215 560.17V601L682.479 609.562V649.29L663.144 647V682.575L682.479 684.723L683.5 814.5L652.402 808.201V839L543.911 819.5V788.874L511.685 783.505V654.5L532.095 658.5V623.52L511.685 620.299V578.424L557.875 585.94V545.138L422.5 521.516L402.12 538.234V654.658V766.326L373.117 762V791.021L311.889 778.5V750L285.035 744.851V512.926L264.5 493.599L155.06 472.125ZM778.08 579.497L780.228 833.971L847.901 781.358V538.234L778.08 579.497ZM561.097 627.5V664.5L543.911 661V788.874L565.394 793.169L567 669L584.729 672V632.5L561.097 627.5ZM611.583 639.626V676.5L628.77 679V802.832L652.402 808.201V682.575L635.215 680.428V643L611.583 639.626Z" fill="currentColor"/>
+</svg>
\ No newline at end of file
index 4eac7dccee0696f4f1aa19607bd7ce1de9257ccb..4843a25244ac4c85c6ea430c641a4c3052750c16 100644 (file)
@@ -19,6 +19,8 @@ const main = useMainStore()
 </script>
 ```
 
+<RuleKitLink />
+
 ## Using the store outside of `setup()`
 
 If you need to use the store somewhere else, you need to pass the `pinia` instance [that was passed to the app](../getting-started.md#installation) to the `useStore()` function call:
index 2a78d672310f25e57019d69fe914633d09672804..f65e9dba5ff80a515cc5587465e1af1a09d70112 100644 (file)
@@ -7,6 +7,8 @@
 
 Using Pinia with [Nuxt](https://nuxt.com/) is easier since Nuxt takes care of a lot of things when it comes to _server side rendering_. For instance, **you don't need to care about serialization nor XSS attacks**. Pinia supports Nuxt Bridge and Nuxt 3. For bare Nuxt 2 support, [see below](#nuxt-2-without-bridge).
 
+<RuleKitLink />
+
 ## Installation
 
 ```bash
index b8b6cd885439cb0e9c186f2c1737751bfbded570..371e959c2cbd8716b94ccb02ad10473886878a12 100644 (file)
@@ -1,5 +1,7 @@
 # 处理组合式函数 %{#dealing-with-composables}%
 
+<RuleKitLink />
+
 [组合式函数](https://cn.vuejs.org/guide/reusability/composables.html#composables)是利用 Vue 组合式 API 来封装和复用有状态逻辑的函数。无论你是自己写,还是使用[外部库](https://vueuse.org/),或者两者都有,你都可以在 pinia store 中充分发挥组合式函数的力量。
 
 ## Option Stores %{#option-stores}%
index 90ac2fa9ac8aef2fb224f7afd70331af0e7b9b03..b07d36730db9a7739a56b9dd1a6ae54ae6ec5aac 100644 (file)
@@ -1,5 +1,7 @@
 # 组合式 Store %{#composing-stores}%
 
+<RuleKitLink />
+
 组合式 store 是可以相互使用,Pinia 当然也支持它。但有一个规则需要遵循:
 
 如果**两个或更多的 store 相互使用**,它们不可以通过 _getters_ 或 _actions_ 创建一个无限循环。它们也不可以**同时**在它们的 setup 函数中直接互相读取对方的 state:
index 68a9a671d40a34aa1c63901bd410d89d07906fc6..76a959ec76b172df25bc5d5102598e61af6f9b59 100644 (file)
@@ -1,5 +1,7 @@
 # HMR (Hot Module Replacement) %{#hmr-hot-module-replacement}%
 
+<RuleKitLink />
+
 Pinia 支持热更新,所以你可以编辑你的 store,并直接在你的应用中与它们互动,而不需要重新加载页面,允许你保持当前的 state、并添加甚至删除 state、action 和 getter。
 
 目前,只有 [Vite](https://cn.vitejs.dev/guide/api-hmr#hmr-api) 被官方支持,不过任何实现 `import.meta.hot` 规范的构建工具都应该能正常工作。(例外的是,[webpack](https://webpack.js.org/api/module-variables/#importmetawebpackhot) 似乎使用的是 `import.meta.webpackHot` 而不是 `import.meta.hot` )
index 22c9b31567ff49ba3e52a554d22f718f18d38bab..a7bd99e4bc4892c989160c7953ea129cbee3c95a 100644 (file)
@@ -1,5 +1,7 @@
 # 手册 %{#cookbook}%
 
+<RuleKitLink />
+
 - [从 Vuex ≤4 迁移](./migration-vuex.md)。用于转换 Vuex ≤4 项目的迁移指南。
 - [HMR](./hot-module-replacement.md):如何激活热更新并改善开发者体验。
 - [测试 Stores (WIP)](./testing.md): 如何对 Store 进行单元测试并在组件单元测试中模拟它们。
index 3f3cb089cc8b1b15a40e4d42aae8540dc63722a2..22cd93322105546538426e2859a7e97392069cda 100644 (file)
@@ -1,5 +1,7 @@
 # 从 0.x (v1) 迁移至 v2 %{#migrating-from-0-x-v1-to-v2}%
 
+<RuleKitLink />
+
 从 `2.0.0-rc.4` 版本开始,pinia 同时支持 Vue 2 和 Vue 3!这意味着,v2 版本的所有更新,将会让 Vue 2 和 Vue 3 的用户都受益。如果你使用的是 Vue 3,这对你来说没有任何改变,因为你已经在使用 rc 版本,你可以查看[发布日志](https://github.com/vuejs/pinia/blob/v2/packages/pinia/CHANGELOG.md)来了解所有更新的详细解释。如果你使用的不是 Vue 3,**那这个指南是为你准备的**!
 
 ## 弃用 %{#deprecations}%
index bae87804dab82c8504c7fe04fb202ffc84c09f73..50f42477bac9c169473b70cd2a579df44b252ad9 100644 (file)
@@ -1,5 +1,7 @@
 # 从 Vuex ≤4 迁移 %{#migrating-from-vuex-≤4}%
 
+<RuleKitLink />
+
 虽然 Vuex 和 Pinia store 的结构不同,但很多逻辑都可以复用。本指南的作用是帮助你完成迁移,并指出一些可能出现的常见问题。
 
 ## 准备 %{#preparation}%
index 3142cafe47c91c314ff57854a376f8c27ca77c53..5b210bfd10eb38e4763a84945dc2b9f961b471fc 100644 (file)
@@ -1,5 +1,7 @@
 # 不使用 `setup()` 的用法 %{#usage-without-setup}%
 
+<RuleKitLink />
+
 即使你没有使用组合式 API,也可以使用 Pinia(如果你使用 Vue 2,你仍然需要安装 `@vue/composition-api` 插件)。虽然我们推荐你试着学习一下组合式 API,但对你和你的团队来说目前可能还不是时候,你可能正在迁移一个应用,或者有其他原因。你可以试试下面几个函数:
 
 - [mapStores](#giving-access-to-the-whole-store)
index 01d3d0cbde4a2dd788d7704d6ef4a2840e530f35..810e3a666f29d5247d212ae4a5d7711b9455ed7a 100644 (file)
@@ -1,5 +1,7 @@
 # store 测试 %{#testing-stores}%
 
+<RuleKitLink />
+
 <MasteringPiniaLink
   href="https://play.gumlet.io/embed/65f9a9c10bfab01f414c25dc"
   title="Watch a free video of Mastering Pinia about testing stores"
index 7ef699553f14dcea57bfd0ba959c8cc025600cff..4d92a3bcfcd4fa85ed58e60acc61c491fbbdf795 100644 (file)
@@ -1,5 +1,7 @@
 # VS Code 代码片段
 
+<RuleKitLink />
+
 有一些代码片段可以让你在 VS Code 中更轻松地使用 Pinia。
 
 通过 <kbd>⇧</kbd> <kbd>⌘</kbd> <kbd>P</kbd> / <kbd>⇧</kbd> <kbd>⌃</kbd> <kbd>P</kbd> 然后输入 `Snippets: Configure User Snippets` 就可以管理用户代码片段。
index 59bfaa69d672af17f0f6ebe5f1fdc45e1a70bf81..778fd66d81150823a450351c3624032860be5f89 100644 (file)
@@ -1,5 +1,7 @@
 # Action %{#actions}%
 
+<RuleKitLink />
+
 <!-- <VueSchoolLink
   href="https://vueschool.io/lessons/synchronous-and-asynchronous-actions-in-pinia"
   title="Learn all about actions in Pinia"
index f71cec6849f8a388ec64fe5f4f2fc3042aa7c8c5..4f73f810a666916ee6bf0b73212c3bf7d002736d 100644 (file)
@@ -1,5 +1,7 @@
 # Getter %{#getters}%
 
+<RuleKitLink />
+
 <!-- <VueSchoolLink
   href="https://vueschool.io/lessons/getters-in-pinia"
   title="Learn all about getters in Pinia"
index 12960e68d7ddbc7cc067ea80fc85ba0a14001b89..f220d548d3b2f239d99e8c49441ba117e0f0ccf1 100644 (file)
@@ -1,5 +1,7 @@
 # 定义 Store %{#defining-a-store}%
 
+<RuleKitLink />
+
 <!-- <VueSchoolLink
   href="https://vueschool.io/lessons/define-your-first-pinia-store"
   title="Learn how to define and use stores in Pinia"
index 102ed3f2dc54904c003f81ed0ca0b03a3490febc..51fa370927add869c1de17f3282c83faf2c5da3f 100644 (file)
@@ -1,5 +1,7 @@
 # 在组件外使用 store %{#using-a-store-outside-of-a-component}%
 
+<RuleKitLink />
+
 <MasteringPiniaLink
   href="https://play.gumlet.io/embed/651ed1ec4c2f339c6860fd06"
   mp-link="https://masteringpinia.com/lessons/how-does-usestore-work"
index bd754c9a7ddd1d29b297b59573ae5a42edb768dd..0eca502a0c8bffb2564956eceebf3a38fd92eadd 100644 (file)
@@ -1,5 +1,7 @@
 # 插件 %{#plugins}%
 
+<RuleKitLink />
+
 <MasteringPiniaLink
   href="https://masteringpinia.com/lessons/What-is-a-pinia-plugin"
   title="Learn all about Pinia plugins"
index cca0a8c56b1fd575fb51db4625dc2adcf1cdf528..f0221e1423c6961ef79bde3e91d8b3cf3709c8ad 100644 (file)
@@ -1,5 +1,7 @@
 # State %{#state}%
 
+<RuleKitLink />
+
 <!-- <VueSchoolLink
   href="https://vueschool.io/lessons/access-state-from-a-pinia-store"
   title="Learn all about state in Pinia"
index b0e2dd0871f2f9343e0d00a39900952f8bb691d8..cf28586b4ebd1ac9f11fb33ffdfd057de36feffe 100644 (file)
@@ -1,5 +1,7 @@
 # 开始
 
+<RuleKitLink />
+
 ## 安装 %{#installation}%
 
 <VueMasteryLogoLink for="pinia-cheat-sheet">
index c23a576dd50ea4c16ca01213625b926c88a8ec7f..c832fb276a6d77738ef0255f04ed49fb3c7785c9 100644 (file)
@@ -18,6 +18,9 @@ hero:
     - theme: alt
       text: Demo 演示
       link: https://stackblitz.com/github/piniajs/example-vue-3-vite
+    - theme: cta rulekit
+      text: RuleKit
+      link: https://rulekit.dev?from=vuerouter
     - theme: cta mastering-pinia
       text: ' '
       link: https://masteringpinia.com
index d2cb1b787e101204ce6181822fae5f54a920b13b..3558b281c954014217f5021ea5f2896460eb6dff 100644 (file)
@@ -31,6 +31,8 @@ Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状
 
 如果你仍然有疑问,请查看[**官方**的 Mastering Pinia 课程](https://masteringpinia.com)。在一开始,我们会介绍如何创建自己的 `defineStore()` 函数,然后我们会转向官方的 Pinia API。
 
+<RuleKitLink />
+
 <VueMasteryLogoLink for="pinia-cheat-sheet">
 </VueMasteryLogoLink>
 
index d5b9bf0fd219882f93e91b50570a26744cb9b566..7f52f35efcbaa93b82166c001da35e670c65a1a3 100644 (file)
@@ -1,5 +1,7 @@
 # 服务端渲染 (SSR) %{#server-side-rendering-ssr}%
 
+<RuleKitLink />
+
 <MasteringPiniaLink
   href="https://masteringpinia.com/lessons/ssr-friendly-state"
   title="Learn about SSR best practices"
index 46b2580d21fbcd9911d480725a8b9e0503f7ff01..76f83802de45963beeff0e70eaf1792a2c7f0e02 100644 (file)
@@ -7,6 +7,8 @@
 
 搭配 [Nuxt](https://nuxt.com/) 的 Pinia 更易用,因为 Nuxt 处理了很多与**服务器端渲染**有关的事情。例如,**你不需要关心序列化或 XSS 攻击**。Pinia 既支持 Nuxt Bridge 和 Nuxt 3,也支持纯 Nuxt 2,[见下文](#nuxt-2-without-bridge)。
 
+<RuleKitLink />
+
 ## 安装 %{#installation}%
 
 ```bash