Closed raphael-bresson closed 3 years ago
Salut Raphaël,
Do you encounter the same issue without vue3-sfc-loader (just using plain Vue3) ?
I just tested it with plain Vue3. It works normally. Which is what I expected since I found many examples on the web of people using $refs this way (maybe with vue 2 though…)
I've prepared a very simple test case that reproduces the bug.
If you comment the line
this.fileName = "APRES";
in App.vue
everything is fine and the ref is not lost.
However on changing that data and then rerendering the DOM the ref is lost. So it would have something to do with rerendering the DOM ?
Hope you can fix this easily 😁
Raphaël,
I think that your issue is related to the way you load the components.
Your loadComponent()
creates a new fresh moduleCache
each time it is called, but vue3-sfc-loader
requires a common moduleCache for all modules/components it loads/use.
vue3-sfc-loader
is designed to be used with the less constraints as possible. You just have to use vue3-sfc-loader's loadModule()
the first time then use usual import
or require()
as you would have done without vue3-sfc-loader
.
eg.
<script>
import comp from './static/components/Component.vue';
export default {
...
components: {
comp,
},
};
</script>
Franck,
Sorry, I don't really understand ?
What do you mean by the first time it is called ? How do I know the function loadComponent
has already been called, the component code compiled and I should import it normally ?
If I add a console.log in loadComponent
, I don't see it being called several times.
Could please update my example with the right way to do ?
Thank you
Raphaël,
Use loadModule()
only once, when you mount your app.
eg.
<!DOCTYPE html>
<html>
<body>
<script src="https://unpkg.com/vue@next/dist/vue.runtime.global.prod.js"></script>
<script src="vue3-sfc-loader.js"></script>
<script>
/* <!-- */
const config = {
files: {
'/component.vue': `
<template>
<span> {{ field }} </span>
</template>
<script>
export default {
name: "comp",
props: {
field: { type: String, default: "" },
},
};
</script>
`,
'/app.vue': `
<template>
<div @click="divClick">
<comp :field="fileName"></comp>
<br />
<comp ref="ref1"></comp>
</div>
</template>
<script>
import comp from './component.vue';
export default {
name: "App",
data() {
return {
fileName: "AVANT",
};
},
methods: {
divClick(event) {
console.log(this.$refs.ref1.$el);
this.fileName = "APRES";
},
},
components: {
comp,
},
};
</script>
`,
}
};
/* --> */
const options = {
moduleCache: { vue: Vue },
getFile: url => config.files[url],
addStyle: () => {},
}
Vue.createApp(Vue.defineAsyncComponent(() => window['vue3-sfc-loader'].loadModule('/app.vue', options))).mount(document.body);
</script>
</body>
</html>
Further calls to import
or require()
are automatically handled by vue3-sfc-loader
.
Also note that, if you need, you can continue to use loadModule()
in your components, but options.moduleCache
must be shared between all calls of loadModule()
HIH
what news?
Sorry, I totally forgot to answer you. I was indeed wondering a few days ago if I had done it. Thank you for your answer. Indeed using loadModule only when mounting my App, on my main component, and using the standard import statement worked and solved my problem. I don't know why I was repeatedly using loadModule. I must have got confused somewhere.
Anyway thanks again and you can close this issue.
Raphael
Hi Franck,
I'm still enjoying your library !
I noticed that if I define a ref for a child component. For example:
and use it in a method, for example:
Then the second time the method is called, I get this error:
It seems like I lose the reference, although the child component still exists. So I ended up storing the ref in a data on the first call like so:
But isn't it a bug ? Or is there something I don't understand or do right ? As a side note is using a ref the right way to reference a child component ?
Thank you for your help,
Merci
Raphaël