无事水,但要好好学习
|

Nolca

园龄:6年9个月粉丝:12关注:9

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,
}
);

本文作者:Nolca

本文链接:https://www.cnblogs.com/nolca/p/18146083

版权声明:本作品采用 收益分享revenue sharing 许可协议进行许可。

posted @   Nolca  阅读(48)  评论(0编辑  收藏  举报
历史上的今天:
2022-04-19 一键搞定 VSCode 下的 C/C++基本开发环境配置
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 ⏩intro 山姆精
  2. 2 🎸吉他 马叉
  3. 3 ☁升调 山姆精
  4. 4 🐦Flutter Virtual Riot/Madi
  5. 5 🎶纯律 山姆精
  6. 6 👻yeah~Color Bass! VR
🎸吉他 - 马叉
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.