diff --git "a/\345\274\240\346\240\207\346\230\237\345\256\211/20240513-pinia.md" "b/\345\274\240\346\240\207\346\230\237\345\256\211/20240513-pinia.md"
new file mode 100644
index 0000000000000000000000000000000000000000..59be493d9e5efe07d7903ea8205b4df1939fb5d2
--- /dev/null
+++ "b/\345\274\240\346\240\207\346\230\237\345\256\211/20240513-pinia.md"
@@ -0,0 +1,371 @@
+### 定义 Store
+
+在深入研究核心概念之前,我们得知道 Store 是用 defineStore() 定义的,它的第一个参数要求是一个独一无二的名字:
+```
+js
+import { defineStore } from 'pinia'
+```
+// 你可以任意命名 `defineStore()` 的返回值,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。
+// (比如 `useUserStore`,`useCartStore`,`useProductStore`)
+// 第一个参数是你的应用中 Store 的唯一 ID。
+export const useAlertsStore = defineStore('alerts', {
+ // 其他配置...
+})
+这个名字 ,也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法,将返回的函数命名为 use... 是一个符合组合式函数风格的约定。
+
+defineStore() 的第二个参数可接受两类值:Setup 函数或 Option 对象。
+
+### Option Store
+与 Vue 的选项式 API 类似,我们也可以传入一个带有 state、actions 与 getters 属性的 Option 对象
+```
+js
+export const useCounterStore = defineStore('counter', {
+ state: () => ({ count: 0 }),
+ getters: {
+ double: (state) => state.count * 2,
+ },
+ actions: {
+ increment() {
+ this.count++
+ },
+ },
+})
+```
+你可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。
+
+### Setup Store
+也存在另一种定义 store 的可用语法。与 Vue 组合式 API 的 setup 函数 相似,我们可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。
+```
+js
+export const useCounterStore = defineStore('counter', () => {
+ const count = ref(0)
+ const doubleCount = computed(() => count.value * 2)
+ function increment() {
+ count.value++
+ }
+
+ return { count, doubleCount, increment }
+})
+```
+在 Setup Store 中:
+
+ref() 就是 state 属性
+computed() 就是 getters
+function() 就是 actions
+注意,要让 pinia 正确识别 state,你必须在 setup store 中返回 state 的所有属性。这意味着,你不能在 store 中使用私有属性。不完整返回会影响 SSR ,开发工具和其他插件的正常运行。
+
+Setup store 比 Option Store 带来了更多的灵活性,因为你可以在一个 store 内创建侦听器,并自由地使用任何组合式函数。不过,请记住,使用组合式函数会让 SSR 变得更加复杂。
+
+Setup store 也可以依赖于全局提供的属性,比如路由。任何应用层面提供的属性都可以在 store 中使用 inject() 访问,就像在组件中一样:
+```
+ts
+import { inject } from 'vue'
+import { useRoute } from 'vue-router'
+
+export const useSearchFilters = defineStore('search-filters', () => {
+ const route = useRoute()
+ // 这里假定 `app.provide('appProvided', 'value')` 已经调用过
+ const appProvided = inject('appProvided')
+
+ // ...
+
+ return {
+ // ...
+ }
+})
+WARNING
+```
+不要返回像 route 或 appProvided (上例中)之类的属性,因为它们不属于 store,而且你可以在组件中直接用 useRoute() 和 inject('appProvided') 访问。
+
+你应该选用哪种语法?
+和在 Vue 中如何选择组合式 API 与选项式 API 一样,选择你觉得最舒服的那一个就好。如果你还不确定,可以先试试 Option Store。
+
+### 使用 Store
+虽然我们前面定义了一个 store,但在我们使用
+```
+TIP
+
+如果你还不会使用 setup 组件,你也可以通过映射辅助函数来使用 Pinia。
+
+你可以定义任意多的 store,但为了让使用 pinia 的益处最大化 (比如允许构建工具自动进行代码分割以及 TypeScript 推断),你应该在不同的文件中去定义 store。
+
+一旦 store 被实例化,你可以直接访问在 store 的 state、getters 和 actions 中定义的任何属性。我们将在后续章节继续了解这些细节,目前自动补全将帮助你使用相关属性。
+
+请注意,store 是一个用 reactive 包装的对象,这意味着不需要在 getters 后面写 .value。就像 setup 中的 props 一样,我们不能对它进行解构:
+```
+vue
+
+```
+### 从 Store 解构
+为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:
+```
+vue
+
+```
+### State
+
+在大多数情况下,state 都是你的 store 的核心。人们通常会先定义能代表他们 APP 的 state。在 Pinia 中,state 被定义为一个返回初始状态的函数。这使得 Pinia 可以同时支持服务端和客户端。
+```
+js
+import { defineStore } from 'pinia'
+
+const useStore = defineStore('storeId', {
+ // 为了完整类型推理,推荐使用箭头函数
+ state: () => {
+ return {
+ // 所有这些属性都将自动推断出它们的类型
+ count: 0,
+ name: 'Eduardo',
+ isAdmin: true,
+ items: [],
+ hasChanged: true,
+ }
+ },
+})
+```
+TIP
+
+如果你使用的是 Vue 2,你在 state 中创建的数据与 Vue 实例中的 data 遵循同样的规则,即 state 对象必须是清晰的,当你想向其添加新属性时,你需要调用 Vue.set() 。参考:Vue#data。
+
+### TypeScript
+你并不需要做太多努力就能使你的 state 兼容 TS。确保启用了 strict,或者至少启用了 noImplicitThis,Pinia 将自动推断您的状态类型! 但是,在某些情况下,您应该帮助它进行一些转换:
+```
+ts
+const useStore = defineStore('storeId', {
+ state: () => {
+ return {
+ // 用于初始化空列表
+ userList: [] as UserInfo[],
+ // 用于尚未加载的数据
+ user: null as UserInfo | null,
+ }
+ },
+})
+
+interface UserInfo {
+ name: string
+ age: number
+}
+```
+如果你愿意,你可以用一个接口定义 state,并添加 state() 的返回值的类型。
+```
+ts
+interface State {
+ userList: UserInfo[]
+ user: UserInfo | null
+}
+
+const useStore = defineStore('storeId', {
+ state: (): State => {
+ return {
+ userList: [],
+ user: null,
+ }
+ },
+})
+
+interface UserInfo {
+ name: string
+ age: number
+}
+```
+### 访问 state
+默认情况下,你可以通过 store 实例访问 state,直接对其进行读写。
+```
+js
+const store = useStore()
+```
+store.count++
+### 重置 state
+使用选项式 API 时,你可以通过调用 store 的 $reset() 方法将 state 重置为初始值。
+```
+js
+const store = useStore()
+```
+store.$reset()
+在 $reset() 内部,会调用 state() 函数来创建一个新的状态对象,并用它替换当前状态。
+
+在 Setup Stores 中,您需要创建自己的 $reset() 方法:
+```
+ts
+export const useCounterStore = defineStore('counter', () => {
+ const count = ref(0)
+
+ function $reset() {
+ count.value = 0
+ }
+
+ return { count, $reset }
+})
+```
+
+### 使用选项式 API 的用法
+
+在下面的例子中,你可以假设相关 store 已经创建了:
+```
+js
+// 示例文件路径:
+// ./src/stores/counter.js
+
+import { defineStore } from 'pinia'
+
+const useCounterStore = defineStore('counter', {
+ state: () => ({
+ count: 0,
+ }),
+})
+```
+如果你不能使用组合式 API,但你可以使用 computed,methods,...,那你可以使用 mapState() 辅助函数将 state 属性映射为只读的计算属性:
+```
+js
+import { mapState } from 'pinia'
+import { useCounterStore } from '../stores/counter'
+
+export default {
+ computed: {
+ // 可以访问组件中的 this.count
+ // 与从 store.count 中读取的数据相同
+ ...mapState(useCounterStore, ['count'])
+ // 与上述相同,但将其注册为 this.myOwnName
+ ...mapState(useCounterStore, {
+ myOwnName: 'count',
+ // 你也可以写一个函数来获得对 store 的访问权
+ double: store => store.count * 2,
+ // 它可以访问 `this`,但它没有标注类型...
+ magicValue(store) {
+ return store.someGetter + this.count + this.double
+ },
+ }),
+ },
+}
+```
+### 可修改的 state
+
+如果你想修改这些 state 属性 (例如,如果你有一个表单),你可以使用 mapWritableState() 作为代替。但注意你不能像 mapState() 那样传递一个函数:
+```
+js
+import { mapWritableState } from 'pinia'
+import { useCounterStore } from '../stores/counter'
+
+export default {
+ computed: {
+ // 可以访问组件中的 this.count,并允许设置它。
+ // this.count++
+ // 与从 store.count 中读取的数据相同
+ ...mapWritableState(useCounterStore, ['count'])
+ // 与上述相同,但将其注册为 this.myOwnName
+ ...mapWritableState(useCounterStore, {
+ myOwnName: 'count',
+ }),
+ },
+}
+```
+TIP
+
+对于像数组这样的集合,你并不一定需要使用 mapWritableState(),mapState() 也允许你调用集合上的方法,除非你想用 cartItems = [] 替换整个数组。
+
+### 变更 state
+
+除了用 store.count++ 直接改变 store,你还可以调用 $patch 方法。它允许你用一个 state 的补丁对象在同一时间更改多个属性:
+```
+js
+store.$patch({
+ count: store.count + 1,
+ age: 120,
+ name: 'DIO',
+})
+```
+不过,用这种语法的话,有些变更真的很难实现或者很耗时:任何集合的修改(例如,向数组中添加、移除一个元素或是做 splice 操作)都需要你创建一个新的集合。因此,$patch 方法也接受一个函数来组合这种难以用补丁对象实现的变更。
+```
+js
+store.$patch((state) => {
+ state.items.push({ name: 'shoes', quantity: 1 })
+ state.hasChanged = true
+})
+```
+
+两种变更 store 方法的主要区别是,$patch() 允许你将多个变更归入 devtools 的同一个条目中。同时请注意,直接修改 state,$patch() 也会出现在 devtools 中,而且可以进行 time travel (在 Vue 3 中还没有)。
+
+### 替换 state
+你不能完全替换掉 store 的 state,因为那样会破坏其响应性。但是,你可以 patch 它。
+```
+js
+// 这实际上并没有替换`$state`
+store.$state = { count: 24 }
+// 在它内部调用 `$patch()`:
+store.$patch({ count: 24 })
+```
+你也可以通过变更 pinia 实例的 state 来设置整个应用的初始 state。这常用于 SSR 中的激活过程。
+```
+js
+pinia.state.value = {}
+```
+### 订阅 state
+类似于 Vuex 的 subscribe 方法,你可以通过 store 的 $subscribe() 方法侦听 state 及其变化。比起普通的 watch(),使用 $subscribe() 的好处是 subscriptions 在 patch 后只触发一次 (例如,当使用上面的函数版本时)。
+```
+js
+cartStore.$subscribe((mutation, state) => {
+ // import { MutationType } from 'pinia'
+ mutation.type // 'direct' | 'patch object' | 'patch function'
+ // 和 cartStore.$id 一样
+ mutation.storeId // 'cart'
+ // 只有 mutation.type === 'patch object'的情况下才可用
+ mutation.payload // 传递给 cartStore.$patch() 的补丁对象。
+
+ // 每当状态发生变化时,将整个 state 持久化到本地存储。
+ localStorage.setItem('cart', JSON.stringify(state))
+})
+```
+默认情况下,state subscription 会被绑定到添加它们的组件上 (如果 store 在组件的 setup() 里面)。这意味着,当该组件被卸载时,它们将被自动删除。如果你想在组件卸载后依旧保留它们,请将 { detached: true } 作为第二个参数,以将 state subscription 从当前组件中分离:
+```
+vue
+
+```
+TIP
+
+你可以在 pinia 实例上使用 watch() 函数侦听整个 state。
+```
+js
+watch(
+ pinia.state,
+ (state) => {
+ // 每当状态发生变化时,将整个 state 持久化到本地存储。
+ localStorage.setItem('piniaState', JSON.stringify(state))
+ },
+ { deep: true }
+)
+```
\ No newline at end of file
diff --git "a/\345\274\240\346\240\207\346\230\237\345\256\211/20240516-\350\267\257\347\224\261\345\272\224\347\224\250.md" "b/\345\274\240\346\240\207\346\230\237\345\256\211/20240516-\350\267\257\347\224\261\345\272\224\347\224\250.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d093f90994e93beb4c3259d35c68c4b91e25b3dc
--- /dev/null
+++ "b/\345\274\240\346\240\207\346\230\237\345\256\211/20240516-\350\267\257\347\224\261\345\272\224\347\224\250.md"
@@ -0,0 +1,29 @@
+### 通过路由方式实现增删改查
+#### 思路:
+1. 配置路由:
+~~~js
+// src/router/router.js
+ import { createRouter, createWebHistory } from 'vue-router';
+ import Home from './components/Home.vue';
+ import ManageItem from './components/Edit.vue';
+ const router = createRouter({
+ history: createWebHistory(),
+ routes:[
+ {path:'/home',component:Home},
+ { path: '/edit/:id?',
+ name: 'Edit',
+ component: Edit,
+ },
+ {path:'/',component:App},
+ // 这里也可以加上redirect:'/home' 表示一打开就跳转到列表页,但是不推荐
+ ]
+ } );
+ export default router;
+~~~
+2. 配置入口文件:
+~~~js
+ import router from '.Router/router';
+ const app = createApp(App);
+ app.use(router);
+~~~
+\ No newline at end of file
\ No newline at end of file