如何装饰装载机方法以与加载指示器组件一起使用?(在 Vue 中)



为了重用指示的加载进度,我创建了一个带有插槽和枚举道具的组件,如下所示:

<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属性并将其作为 prop 传递给组件,但它与主模型无关,它只反映了组件使用的加载状态

似乎只是~装饰加载器并以某种方式将其与某个组件实例连接(使用ref?(就更合适了,但我不确定如何实现这一点。您能提出一种这种装饰/连接的方法吗?

我不确定装饰如何与 Typescript/Vue 一起工作,但在我的一个项目中,我只是使用 mixin 来提供这样的功能。

以下解决方案未经测试,但可以让您大致了解如何使用此mixin来跟踪加载状态:

// 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>

我希望这能给你一些想法。

最新更新