Как украсить методы загрузчика для использования с индикатором загрузки компонентов? (в Vue) - PullRequest
0 голосов
/ 10 января 2020

Чтобы повторно использовать индикатор прогресса загрузки, я создал компонент со слотом и реквизитом перечисления, например:

<template>
    <div class="loaded-listing">
        <div class="loaded-listing__loading-placeholder" v-if="isLoading">
            <some-third-party-indicator ... />
        </div>
        <slot v-else />
        <!-- the Failed status is not displayed yet -->
    </div>
</template>

<script lang="ts">

    export enum loadStatusEnum {
        Loading,
        Loaded,
        Failed
    }

    import { Component, Prop, Vue } from 'vue-property-decorator'
    import { SomeThirdPartyIndicator } from 'some-third-party-indicator'

    @Component({
        props: ['loadStatus'],
        components: { SomeThirdPartyIndicator },
    })
    export default class LoadedListing extends Vue {
        @Prop() readonly loadStatus!: loadStatusEnum;
        get isLoading (): boolean {
            return this.loadStatus == loadStatusEnum.Loading
        }
    }

</script>

Для каждой загрузки в представлении / компоненте я использую его следующим образом:

import LoadedListing, { loadStatusEnum } from '../components/LoadedListing.vue'

export default class SomePage extends Vue {
    ...
    someStuffLoadStatus: loadStatusEnum = loadStatusEnum.Loading; // 1
    loadSomeStuff (): void {
        this.someStuffLoadStatus = loadStatusEnum.Loading; // 2
        this.$store.dispatch('someModule/loadSomeStuff', ...) // some model updating in a callback
            .then(() => this.someStuffLoadStatus = loadStatusEnum.Loaded) // 3
            .catch(() => this.someStuffLoadStatus = loadStatusEnum.Failed) // 4
    }
    ...
}

и в шаблоне:

<LoadedListing class="some-stuff-list" :load-status="someStuffLoadStatus">
    <div class="some-stuff-list__top-panel"> ... </div>
    <VueSimplebar class="some-stuff-list__body" ...> ... </VueSimplebar>
</LoadedListing>

Что мне не нравится в этом подходе:

  • Я пишу строки 1-4 для каждого загрузчика
  • Я создаю свойство someStuffLoadStatus внутри родительского компонента и передаю его как компонент компоненту, но он не имеет ничего общего с основной моделью, он отражает только состояние загрузки, используемое компонентом

кажется, что было бы более адекватным просто декорировать загрузчик и каким-то образом связать его с определенным экземпляром компонента (используя ref?), Но я не уверен, как я могу это реализовать. Не могли бы вы предложить подход к такой отделке / подключению?

1 Ответ

1 голос
/ 10 января 2020

Я не уверен, как оформление будет работать с Typescript / Vue, но в одном из моих проектов я просто использовал миксин для предоставления такой функции.

Следующее решение не протестировано, но дает вам Общая идея о том, как использовать этот миксин для отслеживания состояний загрузки:

// loading_mixin.js
export default {
    data() {
        return {
            loader: {
                // This object will contain various keys you pass to
                // the `wrap()` function `type` parameter.
            }
        }
    },
    methods: {
        /**
         * @param {Promise} promise
         * @param {String} type
         * @returns {Promise}
         */
        wrap(promise, type) {
            let loaded = this.loader[type] ? this.loader[type].loaded : false;
            this.$set(this.loader, type, {loading: true, loaded: loaded});
            return promise.then((data) => {
                this.$set(this.loader, type, {loading: false, loaded: true});
                return data;
            }).catch((err) => {
                this.$set(this.loader, type, {loading: false, loaded: false});
                throw err;
            });
        },
    }
}

Использование (YourComponent.vue):

<template>
    <div>
        <loading-component :loader="loader.load_data" />
    </div>
</template>
<script>
    import loadingMixin from '...';
    export default {
        mixin: [loadingMixin],
        methods: {
            load() {
                this.wrap(this.loadMyData(1, 2), 'load_data').then((data) => {
                    // Handle success.
                }).catch((err) => {
                    // Handle err.
                })
            },
            loadMyData(a, b) {
                return Promise.resolve(a + b);
            }
        }
}
</script>

Надеюсь, это даст вам некоторые идеи.

...