Reputation: 927
I have a sectionHeader.vue
component that I want to use on lots of different pages. Inside that sectionHeader.vue
is a <canvas>
element (that I am using for some robust three.js animations) that I dynamically want to change inside of each header through props. I'd like to get this working to take advantange of Vue's inherent code-splitting so that each page doesn't load every single other pages animation js code, only the code that is relevant to it.
I'm attempting to dynamically load this in using dynamic components but I don't think this is what I'm looking for...
My folder structure:
components
animations
robust-animation-1.vue
robust-animation-2.vue
maybe-like-15-more-of-these.vue
headings
heading2.vue
SectionHeader.vue
pages
index.vue
pages/index.vue:
<sectionHeader post-title="Menu" class-name="menu" canvas="./animations/robust-animation-1"></sectionHeader>
components/SectionHeader.vue:
<template>
<section class="intro section-intro" :class="className">
<heading2 :post-title="postTitle"></heading2>
<component v-bind:is="canvas"></component> <!-- this is what i am dynamically trying to load -->
{{canvas}} <!-- this echos out ./animations/robust-animation-1 -->
</section>
</template>
<script>
import heading2 from './headings/heading2';
export default {
components: {
heading2
},
props: [
'postTitle', 'className', 'canvas'
]
}
</script>
components/animations/robust-animation-1.vue:
<template>
<div>
<canvas class="prowork-canvas" width="960" height="960"></canvas>
</div>
</template>
<script>
// 200 lines of js here that manipulates the above canvas
</script>
My heading2
component works great, but no matter what I try I can't figure out how to dynamically pull in my animation component. I get varying degrees of the below error:
client.js 76 DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('./animations/robust-animation-1') is not a valid name.
I looked into scoped slots, and that looks close to what I need, but not exactly. Is there a better way to do what I'm attempting?
Upvotes: 4
Views: 1149
Reputation: 6978
I have successfully done Dynamically loading in a child component based on a prop
. Please refer to the following code.
components
animations
robust-animation-1.vue
robust-animation-2.vue
maybe-like-15-more-of-these.vue
headings
heading2.vue
SectionHeader.vue
pages
index.vue
vuepages/index.vue:
<section-header post-title="Menu" class-name="menu" canvas="./animations/robust-animation-1">
</section-header>
<script>
import SectionHeader from "../components/SectionHeader";
export default {
name: 'PageIndex',
components: {SectionHeader}
}
</script>
components/SectionHeader.vue:
<template>
<div>
post_title {{postTitle}}
<br/>
class-name {{className}}
<br/>
canvas {{canvas}}
<br/>
<heading2 post-title="postTitle"></heading2>
<br/>
<component v-bind:is="stepComponent"></component>
</div>
</template>
<script>
import Heading2 from "./headings/heading2";
export default {
name: "SectionHeader",
components: {
Heading2,
},
props: ['postTitle', 'className', 'canvas'],
computed: {
stepComponent() {
let data = this.canvas.split('/')[2];
return () => import(`./animations/${data}`);
}
},
}
</script>
You're missing that last computed
step as part of the SectionHeader.vue component
components/animations/robust-animation-1.vue
<template>
<div>
From - robust-animation-1
</div>
</template>
<script>
export default {
name: "robust-animation-1"
}
</script>
Output:
post_title Menu
class-name menu
canvas ./animations/robust-animation-1
postTitle
From - robust-animation-1
Upvotes: 1