Vue DFS 스토어: Vue 내장 반응 기능을 갖춘 간단한 스토어 포장

몇 주 전에 Vue 생태계를 깊이 연구할 때 dev.to에서 재미있는 문장을 발견했는데 제목은.이러한 지도와 Vue 반응 시스템의 소망을 고려하여 반응 시스템을 바탕으로 간단한 저장 실현을 만들어서 쉽게 초기화하고 저장을 제공하며 저장을 Vue 구성 요소에 주입할 수 있는지 알고 싶습니다.
저는 최근에 Zustand을 사용했습니다. 이것은 상태 관리 솔루션으로 주로 React에 사용되고'set'과'get'방법을 통해 상태에 접근할 수 있는 조작의 간단성을 만드는 것을 좋아합니다.물론 Vue의 반응성 시스템은 가변 상태로 작동하기 때문에 React와 조금 다르지만, Zustand에서 제공하는 API와 유사한 API를 원합니다.
나는 지금 내가 최근에 배운 성과를 보여 준다.

Vue DFS 스토어 소개


이걸 어떻게 사용하는지 보여주자...햇빛 아래의 모든 것이 신선한 일이 아니기 때문에, 카운터 프로그램

상점 만들기


우리는 createStore 함수를 사용하고 설정 대상에 다음과 같은 속성을 제공합니다.
import { createStore } from 'vue-dfs-store';

type CounterState = {
  count: number;
};

type CounterAccessors = {
  incCount: (val: number) => void;
  clearCount: () => void;
  multCount: (val: number) => number;
};

const counterStore = createStore<CounterState, CounterAccessors>({
  name: 'counterStore',
  initialState: {
    count: 0,
  },
  accessorsCreator: (mutate, get) => ({
    incCount: (val: number) => mutate(state => (state.count += val)),
    clearCount: () => mutate(state => (state.count = 0)),
    multCount: (val: number) => get().count * val,
  }),
  mutatorHook: state => console.log(state),
});

export default counterStore;

CreateStore 상세 정보


배치 수신 name, initialState 대상(일반 구 대상), accessorsCreatormutatorHookaccessorsCreatormutateget 함수를 수신하고 방법 대상을 되돌려줍니다. 우리는 그 중에서 상태를 얻거나 수정할 수 있습니다.get은 반응 상태의 Vue 읽기 전용 버전에 대한 액세스를 제공합니다.현재 카운터 값의 배수를 계산하기 위해 아래 multCount 액세서리에서 사용할 수 있습니다.
스토리지의 가변 상태는 mutate 방법에서만 액세스할 수 있습니다.이는 Zustand's set 방법과 유사하다.액세서리 내부에서 필요에 따라 임의의 수량의 변이를 할 수 있고 이런 액세서리도 비동기적으로 진행할 수 있다.mutatorHooks은 매번 변이한 후에 코드를 실행하는 데 사용된다.미래에, 나는 공공mutatorHook을 공유하는 여러 개의 저장소를 만들고 싶다. (돌연변이를 제출하기 전과 이후에 코드를 실행하는 기능)이것은 미래의 상태 역사를 저장하는 데 쓸 수 있다.createState의 상태와 액세서리 (위 참조) 에 현식 형식을 제공할 수도 있고, 설정의 추정 형식에 의존할 수도 있습니다.

스토어 속성 만들기


createStore 함수는 다음 내용을 되돌려줍니다. 일반 매개 변수 T와 U는 상태와 액세서리의 형식입니다.
// Store is returned by createStore()
export type Store<T extends State, U extends Accessors> = {
  readonly name: string;
  storeAPI: StoreAPI<T, U>;
  install: (app: App) => void; // makes Store implement Plugin from vue
  readonly storeKey: symbol;
  provider: () => void;
};
저희 구성 요소에서 사용할 주요 속성은 storeAPI입니다. 이것은useStore 함수에서 되돌아오는 내용입니다. 아래와 같습니다.
StoreAPI 유형은 다음과 같습니다.READE에서 제공하는 스크립트(READE에서 제공하는 버전만 READE와 READE에서 제공하는 버전을 볼 수 있음)
export type StoreAPI<T extends State, U extends Accessors> = {
  readonly state: ReadonlyState<ReactiveState<T>>;
  accessors: U;
};

상점을 제공하다

createStore이 반환하는 대상은 install 방법과 provider입니다.
다음과 같이 스토리지를 app.use()에 직접 전달하여 애플리케이션의 루트 디렉토리에 스토리지를 제공할 수 있습니다.
import { createApp } from 'vue';
import App from './App.vue';
import counterStore from './store/counter';

createApp(App)
  .use(counterStore)
  .mount('#app');
트리 구조의 모든 Vue 구성 요소의 설치 방법에서store inside를 가져오고 provider을 호출할 수 있습니다.

상점을 이용하다

useStore 함수를 가져오고 읽기 전용 상태와 액세서리에 접근하기 위한 저장소를 전달합니다.computed에서 multCount 방법을 어떻게 다시 계산하는지 보십시오. 반응 의존항인 multiplier이 업데이트되었을 때.
useStore에서 되돌아오는 반응 상태 대상에 대한 확장이 필요하면 toRefs을 사용하십시오.
<script lang="ts">
import { defineComponent, ref, computed, toRefs } from 'vue';
import { useStore } from 'vue-dfs-store';
import counterStore from '../store/counter';

export default defineComponent({
  name: 'Counter',
  setup() {
    const multiplier = ref(0);
    const { state, accessors } = useStore(counterStore);

    const { count } = toRefs(state);

    const multipliedCount = computed(() =>
      accessors.multCount(multiplier.value)
    );

    return {
      state,
      count,
      incCount: accessors.incCount,
      clearCount: accessors.clearCount,
      multiplier,
      multipliedCount,
    };
  },
});
</script>

자세한 내용!


Github repo을 보고 원본 코드, 문서, 프레젠테이션 프로그램을 어떻게 실행하는지 알아보세요.
만약 당신이 나에게 원본 코드를 보여 주고 싶다면, 나는 다시 한 편의 글을 쓸 것이다.댓글로 알려주세요!

왜 Vuex를 안 써요?


아니...어쨌든 그것을 사용해라!
비록 Vuex은 Vue에서 상태 관리의 뚜렷한 옵션이지만, 나는 곧 다가올 v4에 저장을 입력하는 것이 약간 어렵고 문서가 적거나 최소한 '예시' 가 적다는 것을 확실히 발견했다.Vuex의 Typescript documentation을 보고 하나의 "계수"속성을 가진 저장소를 응용 프로그램에 주입하는 방법을 알아보십시오.아마도 나는 단지 더 많은 연습을 필요로 할 뿐이거나, Vuex팀은 문서를 업데이트하고 블로그 작가에게 더 좋은 예를 제공하기 위해 약간의 시간을 필요로 할 뿐이다.
어쨌든 나는 내가 Vuex를 대체할 수 있다고 생각하지 않기를 원하지 않는다.제가 쓴 바와 같이 저는 단지 Vue 반응 시스템과 합성 API에 대한 정보를 더 알고 싶을 뿐입니다.귀신이 곡할 노릇이군, 내 생각에 중대한 결함이 있을지도 몰라.그렇다면 말씀해 주세요.
만약 당신이 이것이 매우 유용하다고 생각한다면, 아마도 나는 이 프로젝트를 위해 파이프라인을 개발할 것이다. 이렇게 하면 개선 작업이 순조롭게 진행될 수 있을 것이다.

나는 너의 도움이 필요하다

storeAPI에서 toRefs으로 전화를 걸면 주 버전인 useStore()에 직접 액세스할 수 있습니다.그러나 읽기 전용 상태를 ToRefs로 포장할 때 다음과 같은 Typescript 오류가 계속 발생합니다.

error TS2590: Build:Expression produces a union type that is too complex to represent.


나는 확실히 이 문제를 해결하는 방법을 발견했지만, 어떻게 나의 타자 스크립트를 간소화해서 이 문제를 해결할 수 있는지 확정할 수 없다.나의 의심은 vue 반응성 유형의 DeepReadonly의 복잡성에 ToRefs과 이 라이브러리의 유형이 너무 복잡한 유형을 만들었을 뿐이라는 것이다.나는 ToRefs를 사용하여 객체를 쓸 수도 있고 DeepReadonly 객체만 사용할 수도 있다.
다음은 Vue3에서 DeepReadonly(readonly() 포함)를 만들 때 사용하는 유형입니다.
type Primitive = string | number | boolean | bigint | symbol | undefined | null
type Builtin = Primitive | Function | Date | Error | RegExp
export type DeepReadonly<T> = T extends Builtin
  ? T
  : T extends Map<infer K, infer V>
    ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
    : T extends ReadonlyMap<infer K, infer V>
      ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
      : T extends WeakMap<infer K, infer V>
        ? WeakMap<DeepReadonly<K>, DeepReadonly<V>>
        : T extends Set<infer U>
          ? ReadonlySet<DeepReadonly<U>>
          : T extends ReadonlySet<infer U>
            ? ReadonlySet<DeepReadonly<U>>
            : T extends WeakSet<infer U>
              ? WeakSet<DeepReadonly<U>>
              : T extends Promise<infer U>
                ? Promise<DeepReadonly<U>>
                : T extends {}
                  ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
                  : Readonly<T>

좋은 웹페이지 즐겨찾기