跳到主要内容

场景

2024年03月20日
柏拉文
越努力,越幸运

一、状态管理


可以模拟store完成一套更灵活的状态管理又或用于子父组件、兄弟组件、全局通信

1.1 defineStore

import { effectScope } from "vue";

function defineStore(setup){
let state;
let isChange = false;
const scope = effectScope(true);
return ()=>{
if(!isChange){
state = scope.run(setup);
isChange = true;
}
return state;
}
}

export default defineStore;

1.2 useStore

import { computed, ref } from "vue";
import defineGlobalStore from "./defineStore";

const useStore = defineGlobalStore(() => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
const updateCount = () => {
count.value++;
};
return { count, doubleCount, updateCount };
});

export default useStore;

随后, 可以在不同组件中使用

<template>
<div class="b">
<h3> B 组件</h3>
{{ count }}
{{ doubleCount }}
</div>
</template>

<script lang="ts" setup>
import useStore from "./store";

const { count, doubleCount, updateCont } = useStore();
</script>
<template>
<div class="b">
<h3> C 组件</h3>
{{ count }}
{{ doubleCount }}
<button @click="updateCount">C 组件 Update</button>
</div>
</template>

<script lang="ts" setup>
import useStore from "./store";

const { count, doubleCount, updateCount } = useStore();
</script>

二、包装组合函数


2.1 包装 useMouse, 只进行一次监听

import { effectScope, onScopeDispose, ref } from "vue";

function useMouse(){
const x = ref(0);
const y = ref(0);

const updateMouse = (e: MouseEvent) => {
x.value = e.pageX;
y.value = e.pageY;
}

window.addEventListener('mousemove', updateMouse);

onScopeDispose(()=>{
window.removeEventListener('mousemove', updateMouse);
});

return {x,y}
}

function createSharedComposable(composable){
let state;
let scope;
let subscribers = 0;

const dispose = ()=>{
if(scope && --subscribers <= 0){
scope.stop();
state = scope = null;
}
}

return (...args)=>{
subscribers++;
if(!state){
scope = effectScope(true);
state = scope.run(()=> composable(...args));
}
onScopeDispose(dispose);
return state;
}
}

const useShareMouse = createSharedComposable(useMouse);
export default useShareMouse;