Vuejs3/Vuex4 承诺履行时有条件渲染
Vuejs3/Vuex4 conditional render on promise fulfillment
我有自定义的 object 用于保存 child object 的全部数据。 child object 的所有属性均以空值启动,因此可以引用 object 并从远程源填充它们的属性。这将创建一个 lazy-loading 设置。
此代码将极度精简,但所有相关内容都应在此处:
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();
}
}
}
然后 child 看起来像:
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”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);
}
}
});
想法是,每当将 Child
添加到 Collection
时,集合 loaded
属性 将为假,直到所有 Child
加载器承诺解决。这一切都完美执行......除了 loaded
布尔不是反应性的。
现在,我在每个组件的 Created 函数中都有一个 Promise.all
,一旦组件所需的所有 objects 都已解决其“加载器”承诺,它就会将该组件标记为“已加载” .这绝对有效,但并不理想,因为不同的数据将在不同的时间可用,有时屏幕上会同时显示数百个或更多 类。我想要完成的是:
<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 的实用方法?
看起来 Vue's ref
是我需要的:
this.loaded = ref(false);
这有效,至少在 Child
class 上有效。我遇到了某种循环引用问题,无法在 Collection
class 上进行测试,是的,但它应该可以正常工作。
我有自定义的 object 用于保存 child object 的全部数据。 child object 的所有属性均以空值启动,因此可以引用 object 并从远程源填充它们的属性。这将创建一个 lazy-loading 设置。
此代码将极度精简,但所有相关内容都应在此处:
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();
}
}
}
然后 child 看起来像:
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”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);
}
}
});
想法是,每当将 Child
添加到 Collection
时,集合 loaded
属性 将为假,直到所有 Child
加载器承诺解决。这一切都完美执行......除了 loaded
布尔不是反应性的。
现在,我在每个组件的 Created 函数中都有一个 Promise.all
,一旦组件所需的所有 objects 都已解决其“加载器”承诺,它就会将该组件标记为“已加载” .这绝对有效,但并不理想,因为不同的数据将在不同的时间可用,有时屏幕上会同时显示数百个或更多 类。我想要完成的是:
<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 的实用方法?
看起来 Vue's ref
是我需要的:
this.loaded = ref(false);
这有效,至少在 Child
class 上有效。我遇到了某种循环引用问题,无法在 Collection
class 上进行测试,是的,但它应该可以正常工作。