简体   繁体   English

promise 实现上的 Vuejs3/Vuex4 条件渲染

[英]Vuejs3/Vuex4 conditional render on promise fulfillment

I have custom objects for holding child objects full of data.我有自定义对象来保存充满数据的子对象。 The child objects are initiated with null values for all their properties, so the objects can be referenced and their properties filled from remote sources.子对象使用其所有属性的 null 值启动,因此可以引用对象并从远程源填充它们的属性。 This creates a lazy-loading setup.这会创建一个延迟加载设置。

This code is going to be extremely trimmed down, but everything relevant should be here:这段代码将被极度精简,但所有相关的都应该在这里:

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();
        }
    }
}

The child then looks like:孩子看起来像:

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();
         }
     }
}

In Vuex 4 I have these Collections as properties on an "AppData" object in the store:在 Vuex 4 中,我将这些 Collections 作为商店中“AppData”object 的属性:

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);
        }
    }
});

The idea is that whenever a Child is added to a Collection , the collection loaded property will be false until all the Child loader promises resolve.这个想法是,每当将Child添加到Collection时,集合loaded的属性将是 false,直到所有Child加载器承诺解决。 This all executes perfectly... Except that the loaded bools aren't reactive.这一切都完美执行......除了loaded的布尔不是反应性的。

Right now, I have a Promise.all in each component's Created function that flags the component as "loaded" once all the objects needed for the component have had their "loader" promises resolved.现在,我在每个组件的 Created function 中有一个Promise.all ,一旦组件所需的所有对象都已解决其“加载器”承诺,就会将该组件标记为“已加载”。 This absolutely works, but isn't ideal as different data will be available at different times, and there are sometimes hundreds or more of these classes on screen at once.这绝对有效,但并不理想,因为不同的数据将在不同的时间可用,有时屏幕上会同时显示数百个或更多此类。 What I'm trying to accomplish is:我想要完成的是:

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

So I have two thoughts on overcoming this, either of which would be great:所以我有两个关于克服这个问题的想法,其中任何一个都会很棒:

  • VueJS3 no longer has a need for Vue.set(), because Proxies. VueJS3 不再需要 Vue.set(),因为 Proxies。 How would I make the loaded bools here reactive then?那么我如何让这里loaded的布尔值反应呢? Or more specifically, what am I doing that prevents this from working?或者更具体地说,我在做什么阻止它工作?

  • Alternatively, is there a practical way to use the loader promise directly in a template?或者,有没有一种实用的方法可以直接在模板中使用loader promise?

It looks like Vue's ref is what I needed:看起来Vue 的ref是我需要的:

this.loaded = ref(false);

This works, at least on the Child class.这至少在Child class 上有效。 I have some sort of circular referencing issue going on and haven't been able to test on the Collection class yes, but it should work the same.我遇到了某种循环引用问题,并且无法在Collection class 上进行测试,是的,但它应该可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM