pinia vue3
修改值
https://blog.csdn.net/qq_42543244/article/details/123407045
只修改一个值:直接修改
请注意,store 是一个用 reactive 包装的对象,这意味着不需要在 getters 后面写 .value。就像 setup 中的 props 一样,我们不能对它进行解构 https://pinia.vuejs.org/zh/core-concepts/#using-the-store
@/stores/app.ts
import { defineStore } from "pinia"; const initState = { myState = 0; err: { msg: "", show: false, }, save2tau: false, }; export const useAppStore = defineStore("app", { state: () => initState, actions: { complexUpdate(x: number) { //随便写的复杂逻辑 this.myState += this.myState + x; if (this.save2tau) this.myState %= 5; return "I 💔 前端"; }, }, persist: true, });
index.vue中的<script setup>部分
import { useAppStore } from "@/stores/app"; const appS = useAppStore(); appS.myState=1;
修改多个值:appStore.$patch({})
index.vue中的<script setup>部分
import { useAppStore } from "@/stores/app"; const appS = useAppStore(); appS.$patch({myState: 1, save2tau: true});
逻辑更复杂:actions内定义
见上文的complexUpdate
函数
双向绑定ref()
v-bind
、:某属性
是只读单向的
v-model
是双向数据更新的,这时需要使用storeToRefs
<input v-model="appR.myState" />
import { useAppStore } from "@/stores/app"; import { storeToRefs } from "pinia"; const appS = useAppStore(); const appR = storeToRefs(appS);
此时appR.myState.value === appS.myState
为true,appR.myState.value = 1
等价于appS.myState = 1
引用传递/浅拷贝/指针ref()、值传递/深拷贝实际值.value
https://course.rs/basic/ownership/ownership.html#转移所有权
python的=
赋值都是浅拷贝
js,基本数据类型number, boolean, string
都是深拷贝,其余Object, [], function: () => Object
浅拷贝。
rust中,基本数据类型str, slice
都是深拷贝,其余包装对象都为浅拷贝。
// 浅拷贝,只复制值 const current = appS.myMediaList[appS.currentMediaId];
// 函数浅拷贝,调用current().myState,精简代码 // 小心appS.currentMediaId<0时,数组会越界访问 const current = () => appS.myMediaList[appS.currentMediaId];
这时watch就能监听到变化了。
watch(current, (current) => { pause(); appS.curTime = 0; refresh(); if (audio) play(); });
打包$patch,执行自定义函数
type MyType = typeof initState; export const useAppStore = defineStore("app", { state: () => initState, actions: { update(partial: Partial<MyType>) { // 更新前 this.$patch(partial); // this.$state = { ...this.$state, ...partial }; // 更新后 } } });
watch in pinia
当pinia内部有状态变化时,自动触发某函数
https://github.com/vuejs/pinia/discussions/794
注意,要让 pinia 正确识别 state,你必须在 setup store 中返回 state 的所有属性。这意味着,你不能在 store 中使用私有属性。不完整返回会影响 SSR ,开发工具和其他插件的正常运行。
每个单文件,都可以用不同的api写法
选项式api: export default
- 写起来像
json配置
- 一般来说,插件配置
.ts
建议用选项式api,避免出现插件预料之外的情况:如SSR - 可以使用多个<script>导出,把同一逻辑代码集中在一起。
组合式api: script setup
- 项目初期写
.vue
时会很快,因为写起来更像原生ts
代码 - 共享变量作用域
- hacky的写法,突破插件限制
- 但也比选项式更难纠错
- 需要掌握vue的生命周期:
script setup
/export default
→ template/style → 子组件
坑
reactiveObj = {...reactiveObj, ...partial} Object.assign(reactiveObj, partial);
Object.assign 会修改,而使用扩展运算符的方法会创建一个新的对象。
很骚的写法
// Utilities import { defineStore } from "pinia"; import { MediaItem } from "@/types"; import { Store } from "@tauri-apps/plugin-store"; const DEBOUNCE_TIME = 1000; const REPEAT_TIME = 5000; const DEFAULT_KEY = "initS"; let tauS = new Store("app.bin"); export const useAppStore = defineStore( "app", () => { const isTauri = inject("isTauri") as boolean; async function tauSet(val: any, key: string = DEFAULT_KEY) { if (isTauri) return await tauS.set(key, val); } async function tauGet(key: string = DEFAULT_KEY) { if (isTauri) return await tauS.get(key); } /** * @param key: string, will be abandoned. 临时方案 */ class Watch{ timerDebounce?: NodeJS.Timeout | null; timerRepeat?: NodeJS.Timeout | null; stop( ref: Ref<any> | UnwrapNestedRefs, func?: Function | null, key?: string ) { return watch(ref, (newState) => { // console.log("watch", this.timerRepeat, timerDebounce); if (this.timerDebounce) { clearTimeout(this.timerDebounce); this.timerDebounce = null; } this.timerDebounce = setTimeout(() => { if (this.timerRepeat) { clearInterval(this.timerRepeat); this.timerRepeat = null; // 坑爹 } if (func) func(newState, key); console.log("saved after debounce mode", this.timerDebounce, key); // console.log("saved in debounce mode", ref); }, DEBOUNCE_TIME); if (!this.timerRepeat) { this.timerRepeat = setInterval(() => { if (func) func(newState, key); console.log("saved in repeat mode", this.timerRepeat, key); }, REPEAT_TIME); if (func) func(newState, key); console.log("saved before repeat mode", this.timerRepeat, key); } }); } } const curTime = ref(0); /** * ### Put non-continuously updated variables into initS~~tatic~~ * 将非持续性的变量放到initS中。 * * 假设:进度条秒数在播放后,是持续更新的;那么偶尔更新的变量,就叫非持续性变量. */ let initS = reactive({ myMediaList: [] as MediaItem[], currentMediaId: 0, selected: [] as number[], isLoop: false, isRandom: false, err: { msg: "", show: false, }, save2tau: false, }); type UnwrapNestedRefs = typeof initS; const initR = toRefs(initS); function addCurrentId(x: number) { initS.currentMediaId += initS.myMediaList.length + x; initS.currentMediaId %= initS.myMediaList.length; } if (isTauri) { tauGet().then((data) => { if (data) { console.log("hydrate", data); initS = { ...initS, ...(data as UnwrapNestedRefs) }; } }); tauGet("curTime").then((data) => { if (data) { console.log("hydrate", data); curTime.value = data as number; } }); } const stop_curTime = new Watch().stop(curTime, tauSet, "curTime"); const stop_S = new Watch().stop(curTime, tauSet); return { ...initR, curTime, stop_curTime, stop_S, addCurrentId, }; }, { persist: true, } );
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-04-19 一键搞定 VSCode 下的 C/C++基本开发环境配置