2

我有自定义对象来保存充满数据的子对象。子对象的所有属性都使用空值启动,因此可以引用对象并从远程源填充它们的属性。这会创建一个延迟加载设置。

这段代码将被极度精简,但所有相关的都应该在这里:

class Collection extends Object {
    constructor(){
        this.loaded = false;
        var allLoaders = [];
        var loaderPropmises = [];
        var resolver;
        const $this = this;
        var trackLoaders = function(){
            $this.loaded = false;
            loaderPromises.push(Promise.all(allLoaders).then(() => {
                //... irrelevant logic in here to ensure only the latest promise sets loaded to true
                $this.loaded = true; //This is getting called where I expect
                resolver(); 
            }));
        }
        
        //hook for outside things to watch the promise if they want
        this.loader = new Promise((resolve) => {
            //this only gets resolved once, which is fine
            resolver = resolve;
        });


        //... bunch of code around adding child objects, but the important part:
        this.add(child){
            this[child.id] = child;
            this.allLoaders.push(child.loader); 
            trackLoaders();
        }
    }
}

孩子看起来像:

class Child extends Object {
     constructor(){
         this.loaded = false;
         var resolver;
         const $this = this;
         this.loader = new Promise((resolve) => {
             resolver = resolve;
         }).then((){
             $this.loaded = true;
         });

         this.populate(data){
             //bunch of stuff to set data to properties on this object
             resolver();
         }
     }
}

在 Vuex 4 中,我将这些集合作为商店中“AppData”对象的属性:

const store = createStore({
    state: function(){
        AppData: {}
    },
    mutations: {
        setupCollection(state, name){
            if (!Object.hasOwnProperty.call(state.AppData, name){
                state.AppData[name] = new Collection();
            }
        }
    },
    actions: {
        //this is called on each row of data returned from an Axios call
        add (context, {name, data}){
            context.state.AppData[name][data.id].populate(data);
        }
    }
});

这个想法是,每当将 aChild添加到 aCollection时,集合loaded属性将是 false,直到所有Child加载器承诺解决。这一切都完美地执行......除了loaded布尔不是反应性的。

现在,我Promise.all在每个组件的 Created 函数中都有一个,一旦组件所需的所有对象都解决了它们的“加载器”承诺,就会将该组件标记为“已加载”。这绝对有效,但并不理想,因为不同的数据将在不同的时间可用,有时屏幕上会同时显示数百个或更多这些类。我想要完成的是:

<div v-if="!myCollection.loaded">
    Loading...
</div>
<div v-else>
    Show the data I want here {{myCollection.property}}
</div>

所以我有两个关于克服这个问题的想法,其中任何一个都会很棒:

  • VueJS3 不再需要 Vue.set(),因为 Proxies。那么我如何让loaded这里的布尔值反应呢?或者更具体地说,我在做什么阻止它工作?

  • 或者,有没有一种实用的方法可以loader直接在模板中使用 Promise?

4

1 回答 1

1

看起来Vueref是我需要的:

this.loaded = ref(false);

这至少在Child课堂上有效。我遇到了某种循环引用问题,并且无法在Collection课堂上进行测试,是的,但它应该可以正常工作。

于 2022-01-31T07:30:15.010 回答