vaflya
@vaflya
Ничего личного, это всего лишь хобби.

Как правильно писать на TypeScript VUEX модули?

Как работать с VUEX, когда используешь Typescript?

В интернете видел множество методик и несколько библиотек для декораторов и классов (про поддержку в VUE3 и VUEX4 знаю).

В данный момент я работаю таким методом:

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
import { namespace } from 'vuex-class';
import Navigation from '@/components/Navigation.vue';
import EmotionsPalette from '@/components/emotions-palette/index.vue';

const vdpStore = namespace('vdp');

@Component({
    components: {
        Navigation,
        EmotionsPalette,
    },
})
export default class VDPIndexPage extends Vue {
    // Ссылка на файл с видеоуроком
    private videoLessonSRC!: 'http://localhost:3000/webinar.mp4';
    private groups!: {
        a: 'ege_11_onl_group_soc_normal_max_w1_050919_558_ku_web';
    };

    @vdpStore.State
    private lessonMetricsData!: string;

    @vdpStore.State
    private loading!: boolean;

    @vdpStore.Action
    public getProcessedDataResult!: () => void;

    mounted() {
        this.getProcessedDataResult();
    }

    /**
     * Установить указаное время в видео плеере
     * @param timeCode - новое значение времени
     */
    setTimeVideoPlayer(timeCode: number) {
        // @ts-ignore
        document.getElementById('vid1').currentTime = timeCode - 5;
        console.log('Новое время', timeCode);
    }

    /**
     * Приводит время в секундах к формату HH:MM:SS
     * @param {String} timeSeconds - время в секундах
     */
    formatTime(timeSeconds: string) {
        const sec_num = parseInt(timeSeconds, 10);
        let hours = Math.floor(sec_num / 3600);
        let minutes = Math.floor((sec_num - hours * 3600) / 60);
        let seconds = sec_num - hours * 3600 - minutes * 60;

        if (hours < 10) {
            hours = '0' + hours;
        }
        if (minutes < 10) {
            minutes = '0' + minutes;
        }
        if (seconds < 10) {
            seconds = '0' + seconds;
        }
        return hours + ':' + minutes + ':' + seconds;
    }
}
</script>

В данном решении, мне не нравится, что TS не может проверить наличие состояния или экшена в модуле vuex, к примеру:

@vdpStore.State
    private lessonMetricsData!: string;

    @vdpStore.State
    private loading!: boolean;

Или покажите пожалуйста эталонную репу с использованием vuex nuxt и TS.
  • Вопрос задан
  • 535 просмотров
Решения вопроса 1
@Arsync
Попробуйте библиотеку "vuex-class-modules". Модули ложатся идеально. Особенность именно этой либы в том, что $store можно передать в конструктор модуля прямо внутри компонента, тем самым зарегистрировав модуль не во время компиляции через декоратор как в других решениях, а на этапе выполнения (что может оказаться важным при работе в режиме SSR, где store создаётся вызовом функции createStore(); до монтирования корневого инстанса Vue).
<!-- App.vue -->
<template>
  <div id="q-app">
    <router-view />
  </div>
</template>

<script lang="ts">
import { ExampleModule } from 'src/store/module-example';

export default {
  name: 'App',

  created() {
    const myModule = new ExampleModule({ store: this.$store, name: 'example'});

    myModule.setProp(false); // Mutation calling;

    myModule.confirmProp(); // Action calling
  }
};
</script>

Файл модуля:
// src/store/module-example/index.ts
import {
  VuexModule, Module, Mutation, Action
} from 'vuex-class-modules';

@Module
export class ExampleModule extends VuexModule {
  prop: boolean = false;

  @Mutation
  setProp(payload: boolean) {
    this.prop = payload;
  }

  @Action
  confirmProp() {
    this.setProp(true);
  }
}


Гораздо более популярная библиотека - "vuex-module-decorators", в ней тоже есть принцип, похожий на описанный выше и совместимый с SSR. Пример можно найти здесь.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы