Closed ITrun90 closed 3 years ago
Hi ITrun90,
with the following component hierarchy :
main
foo
bar
I get the following result :
main created
foo created
bar created
bar mounted
foo mounted
main mounted
Isn't this expected ?
Hi Franck,
thank your for reply :)
This would be the expected output. In my example, it is vice versa. Maybe there is a mistake i made, but i followed your instructions in the examples of your documentation.
I guess we can figure it out by reviewing my code.
This is my HTML-Structure:
<div id="test"> <lbsite id="site"> <lbcontainer id="container"> Test </lbcontainer> </lbsite> </div>
And here you find my javascript:
<script> const options = { moduleCache: { vue: Vue, }, async getFile(url) { const res = await fetch(url); if ( !res.ok ) throw Object.assign(new Error(url+' '+res.statusText), { res }); return await res.text(); } }; const defaultOptions = { data: function() { return { eventBus } }, delimiters: ['%%', '%%'] }; const lbsite = loadModule('js/components/site.vue', options); const lbspinner = loadModule('js/components/spinner.vue', options); const lbcontainer = loadModule('js/components/container.vue', options); var newApp = createApp(defaultOptions); newApp.component("lbsite", Vue.defineAsyncComponent( () => lbsite )); newApp.component("lbcontainer", Vue.defineAsyncComponent( () => lbcontainer )); newApp.component("lbspinner", Vue.defineAsyncComponent( () => lbspinner )); newApp.mount("#test"); </script>
Here are the important Vue-SFCs:
site.vue (lbsite)
<template> <div :id="id"> <lbspinner v-show="loading"></lbspinner> <div :class="[{hide_content: loading}]"> <slot></slot> </div> </div> </template> <script> module.exports = { "props": { "id": { type: String, required: true } }, "data": function() { return { "loading": true } }, "mounted": function() { this.loading = false; console.log("Mount: site"); } } </script>
container.vue (lbcontainer)
<template> <div :id="containerID"> <slot></slot> </div> </template> <script> module.exports = { props: { "id": { type: String, default: "lbcontainer" } }, data: function() { return { "containerID": this.id } }, mounted: function() { console.log("Mount: Container"); }, methods: { } } </script>
The output i would expect is: Mount: Container Mount: Site
but the output i get is: Mount: Site Mount: Container
Maybe this will help.
Hi,
A simplified version of your example (please adjust if needed) without vue3-sfc-loader
:
<!DOCTYPE html>
<html>
<body>
<script src="https://unpkg.com/vue@next/dist/vue.global.js"></script>
<script>
Vue.createApp({
template: '<foo><bar>test</bar></foo>',
components: {
foo: {
template: 'foo (<slot></slot>)',
created: () => console.log('foo created'),
mounted: () => console.log('foo mounted'),
},
bar: {
template: 'bar (<slot></slot>)',
created: () => console.log('bar created'),
mounted: () => console.log('bar mounted'),
},
},
created: () => console.log('main created'),
mounted: () => console.log('main mounted'),
}).mount(document.body);
</script>
</body>
</html>
output:
foo (bar (test))
console:
main created
foo created
bar created
bar mounted
foo mounted
main mounted
Hi Franck,
thank you for your reply.
Your example is working as expected, but everytime i use vue3-sfc-loader the parent is mounted before the children. That's why i opened this issue.
Same example with vue3-sfc-loader
:
<!DOCTYPE html>
<html>
<body>
<script src="https://unpkg.com/vue@next/dist/vue.runtime.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue3-sfc-loader/dist/vue3-sfc-loader.js"></script>
<script>
/* <!-- */
const config = {
files: {
'/main.vue': `
<template>
<foo><bar>test</bar></foo>
</template>
<script>
import foo from './foo.vue'
import bar from './bar.vue'
export default {
components: {
foo,
bar,
},
created: () => console.log('main created'),
mounted: () => console.log('main mounted'),
}
</script>
`,
'/foo.vue': `
<template>
foo (<slot></slot>)
</template>
<script>
export default {
created: () => console.log('foo created'),
mounted: () => console.log('foo mounted'),
}
</script>
`,
'/bar.vue': `
<template>
bar (<slot></slot>)
</template>
<script>
export default {
created: () => console.log('bar created'),
mounted: () => console.log('bar mounted'),
}
</script>
`
}
};
/* --> */
const options = {
moduleCache: { vue: Vue },
getFile: url => config.files[url],
addStyle: () => {},
}
Vue.createApp(Vue.defineAsyncComponent(() => window['vue3-sfc-loader'].loadModule('/main.vue', options))).mount(document.body);
</script>
</body>
</html>
output:
foo (bar (test))
console:
main created
foo created
bar created
bar mounted
foo mounted
main mounted
It would seem that the result is exactly the same with and without vue3-sfc-loader
.
... hovever :
<!DOCTYPE html>
<html>
<body>
<script src="https://unpkg.com/vue@next/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
template: '<foo><bar>test</bar></foo>',
created: () => console.log('main created'),
mounted: () => console.log('main mounted'),
})
app.component("foo", Vue.defineAsyncComponent({
loader: () => Promise.resolve({
template: 'foo (<slot></slot>)',
created: () => console.log('foo created'),
mounted: () => console.log('foo mounted'),
})
}));
app.component("bar", Vue.defineAsyncComponent({
loader: () => Promise.resolve({
template: 'bar (<slot></slot>)',
created: () => console.log('bar created'),
mounted: () => console.log('bar mounted'),
})
}));
app.mount(document.body);
</script>
</body>
</html>
output:
foo (bar (test))
console:
main created
main mounted
foo created
foo mounted
bar created
bar mounted
I'm closing this as answered. Discussion can continue if needed.
Hi Franck,
thanks for your help. I got an answer from the vue-team. They say that this is expected behavior when we use „defineAsyncComponent“. Is there a way how I can use your Loader without Vue.defineAsyncComponent? Maybe a non-async way?
Yes, look closer to this : https://github.com/FranckFreiburger/vue3-sfc-loader/issues/21#issuecomment-786463201
Describe the bug
The "mounted"-hook of a parent is called before "mounted"-hook of child.
I have a Component "MyParent" and a Component "MyChild". There is literally nothing in it just in the "mounted-hook" a console.log("Parent is mounted") and console.log("Child is moutned").
The result is: "Parent is mounted" "Child is mounted"
but i would expect that the result is "Child is mounted" "Parent is mounted"
To Reproduce Write the two SFCs. Maybe do something in the child that cost a bit time. Run a console.log() in both and check the order.
Expected behavior I expect that the child is mounted before the parent is mounted. Here is what i expect: https://codesandbox.io/s/peaceful-benz-m0ljx?file=/src/App.vue:275-318
Versions