diff --git "a/\347\274\252\346\242\223\344\272\250/20240513-PiniaAPI.md" "b/\347\274\252\346\242\223\344\272\250/20240513-PiniaAPI.md" new file mode 100644 index 0000000000000000000000000000000000000000..46a8f112b58c3d4f9ba90564697d8428dea3431a --- /dev/null +++ "b/\347\274\252\346\242\223\344\272\250/20240513-PiniaAPI.md" @@ -0,0 +1,202 @@ +### 一、什么是状态管理 +- 对于大项目来说,组件多,状态零散分布在许多组件和组件之间的交互操作中,这时候就需要状态管理,理论上来说,每一个 Vue 组件实例都已经在“管理”它自己的响应式状态了 +- 示例如下: + +```html + + + + + +``` + +- 上面代码中,当add方法不断被调用时,count的值就会不断增加显示在页面上,这样叫做“状态自管理”,由以下几个部分组成: + - 状态(state):驱动整个应用的数据源 + - 视图(view):对状态的一种声明式映射 + - 交互(actions):状态根据用户在视图中的输入而作出相应变更的可能方式 + + 但是以上只是一个单向数据流,即从view上出发action改变state,state的改变最终回到view上,然而,当我们有多个组件共享一个共同的状态时,就会出现以下问题: + - 多个组件依赖于同一状态 + - 来自不同视图的交互也可能需要更改同一份状态 + +### 二、使用Pinia实现状态管理 +#### 1.安装 + +```js +npm install pinia +``` + +#### 2.创建pinia实例 + +```js +// main.js +import {createPinia} from 'pinia'; +let app = createApp(App); +const pinia = createPinia(); +app.use(pinia); +``` + +#### 3.pinia的基本用法 +##### 1.创建store实例 + +```js +// stores/counter.js +import { defineStore } from 'pinia'; + +// Option对象写法 +export const useCountStore = defineStore('count',{ + state:()=>{ + return {count:0} + }, + // 也可以写为 + // state: () => ({ count: 0 }),这里用大括号是为了让他以对象的形式返回出来 + actions:{ + onClick(){ + this.count++ + } + } +}) + +// Setup函数写法 +export const useCountStore = defineStore('count',()=>{ + let count = ref(0); + function onClick(){ + count.value++; + }; + return{count,onClick} +}) +``` + +store的参数: + - 第一个参数要求不可重复 + - 第二个参数可以接受两种类型的值:Setup函数或Option对象 + - Setup: + - ref() 就是 state 属性,computed() 就是 getters,computed() 就是 getters + - 在 setup store 中返回 state 的所有属性 + - Option:state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods) +##### 2.在组件中使用store + +```html + + +``` + +从store解构 +为了从 store 中提取属性时保持其响应性,需要使用 storeToRefs(),但是可以直接从 store 中解构 action + +```js +import {storeToRefs} from 'pinia'; +const counter = useCountStore(); +// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性 +const {count} = storeToRefs(counter); +// 作为 action 的 onClick 可以直接解构 +const {onClick} = counter +``` + +### 三、State +#### 1.概念 +state是 store 的核心,被定义为一个返回初始状态的函数 +#### 2.访问 + +```js +const counter = useCountStore(); +// 访问的是state的初始状态 +// 也可以直接对其读写 +const data = counter.count; +``` +#### 3.重置 +通过调用 store 的 $reset() 方法将 state 重置为初始值 + +```js +// counter.js +export const useCountStore = defineStore('count',()=>{ + let count = ref(0); + function onClick(){ + count.value++; + }; + // 创建自己的 $reset() 方法 + function $reset(){ + count.value=0; + } + return{count,onClick,$reset} +}) +``` + +```html + + + + +``` +#### 4.变更 +用 store.count++ 直接改变 store,还可以调用 $patch 方法 +#### 5.替换 +不能完全替换掉 store 的 state,因为那样会破坏其响应性,还是使用patch + +### 四、Getter +Getter 完全等同于 store 的 state 的计算属性 + +```js +export const useCountStore = defineStore('count',{ + state:()=>{ + return {count:1} + }, + actions:{ + onClick(){ + this.count++ + } + }, + getters: { + doubleCount: (state) => state.count * 2, + }, +}) +``` +- 大多数时候,getter 仅依赖 state,不过,有时它们也可能会使用其他 getter,通过 this,你可以访问到其他任何 getter +- getter 只是幕后的计算属性,所以不可以向它们传递任何参数。不过,你可以从 getter 返回一个函数,该函数可以接受任意参数 + +```js +export const useUsersStore = defineStore('users', { + getters: { + getUserById: (state) => { + // 可以返回函数,这个返回的函数可以接受容易参数 + return (userId) => state.users.find((user) => user.id === userId) + }, + }, +}) + // 调用 +``` + +### 五、Action +Action 相当于组件中的方法,也可通过 this 访问整个 store 实例,而且是可以异步的 \ No newline at end of file diff --git "a/\347\274\252\346\242\223\344\272\250/20240516-\345\244\215\344\271\240\344\273\243\347\240\201.md" "b/\347\274\252\346\242\223\344\272\250/20240516-\345\244\215\344\271\240\344\273\243\347\240\201.md" new file mode 100644 index 0000000000000000000000000000000000000000..87ece2d1b83e546648743e2b9611cf4aedddb583 --- /dev/null +++ "b/\347\274\252\346\242\223\344\272\250/20240516-\345\244\215\344\271\240\344\273\243\347\240\201.md" @@ -0,0 +1,261 @@ +## app.vue + +```vue + + + + + + +``` + +## app.js + +```js +import Koa from 'koa' +import bodyparser from 'koa-bodyparser' +import Router from 'koa-router' +import cors from 'koa2-cors' +import { Sequelize, DataTypes, Op, where } from 'sequelize' + +let app = new Koa(); +let router = new Router(); + +let sequelize = new Sequelize('userDB', 'sa', '123456', { + dialect: "mssql", + host: "localhost" +}) + +let User = sequelize.define('users', { + name: { type: DataTypes.STRING }, + age: { type: DataTypes.INTEGER } +}) + +User.sync() + +router.get('/user/:id?', async (ctx) => { + let id = ctx.params.id * 1 + let keyword = ctx.query.keyword + let data + if (keyword) { + data = await User.findAll({ + where: { + [Sequelize.Op.or]: [ + { id: { [Sequelize.Op.like]: "%" + keyword + "%" } }, + { name: { [Sequelize.Op.like]: "%" + keyword + "%" } }, + { age: { [Sequelize.Op.like]: "%" + keyword + "%" } }, + ] + } + }) + } else if (id) { + data = await User.findByPk(id) + } else { + data = await User.findAll() + } + ctx.body = { + msg: "查询成功", + code: 3000, + data: data + } +}) + +router.del('/user/:id', async (ctx) => { + let id = ctx.params.id * 1 + let data = await User.destroy({ + where: { id: id } + }) + ctx.body = { + msg: "删除成功", + code: 3000, + data: data + } +}) + +router.put('/user/:id', async (ctx) => { + let id = ctx.params.id * 1; + let obj = ctx.request.body; + let item = await User.findByPk(id) + let data + if (item) { + data = await User.update(obj, { + where: { id: id } + }) + ctx.body = { + msg: "修改成功", + code: 3000, + data: data + } + } else { + ctx.body = { + msg: "修改失败", + code: 4000, + data: data + } + } +}) + +router.post('/user',async(ctx)=>{ + let obj = ctx.request.body + let data + if(obj){ + data = await User.create(obj) + ctx.body = { + msg:"新增成功", + code:3000, + data:data + } + }else{ + ctx.body = { + msg:"新增失败", + code:4000, + data:data + } + } +}) + +app.use(bodyparser()) +app.use(cors()) +app.use(router.routes()) + +app.listen(3000,()=>{ + console.log(`服务已打开于:http://localhost:3000`); +}) +``` \ No newline at end of file