I am building a Vue3 app which uses vue-router
. I initialized the <router-view />
component and the necessary router-links
. When I click on a <router-link>
element, I am taken to the corresponding page, but the JavaScript modules I used (apexcharts
, fontawesome
, ...) are not loading.
An example of this is the <i>
element, which the fontawesome
package should render as an icon. Here is a snippet from my source code where I use this:
<i class="ti-trash"></i> Cancel
The <i>
element can be found in the HTML by using the Chrome DevTools, but it is not rendered into an icon, which is what I would have wanted to happen.
Here are relevant snippets of my source code:
main.js
:
import { createApp } from 'vue'
import Dashboard from '@/components/Dashboard.vue'
import InstanceCreationForm from '@/components/InstanceCreationForm.vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from "@/App.vue";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: Dashboard
},
{
path: '/create-instance',
component: InstanceCreationForm
}
]
})
const app = createApp(App)
app.use(router)
app.mount('#app')
Dashboard.vue
:
<template>
<main-template>
<template v-slot:content>
<router-link to="/create-instance">
Add New
</router-link>
</template>
</main-template>
</template>
<script>
import "../js/vendors.min.js" // <-- Contains jQuery, fontawesome
import "../assets/icons/feather-icons/feather.min.js"
import "../assets/vendor_components/apexcharts-bundle/dist/apexcharts.js"
import "../js/demo.js"
import "../js/jquery.smartmenus.js"
import "../js/menus.js"
import "../js/template.js"
import "../js/pages/dashboard.js"
import MainTemplate from "@/components/MainTemplate.vue";
export default {
name: "Dashboard",
extends: MainTemplate,
components: {MainTemplate}
metaInfo: {
script: [
{src: "https://cdn.amcharts.com/lib/4/core.js", async: true, defer: true},
{src: "https://cdn.amcharts.com/lib/4/charts.js", async: true, defer: true},
{src: "https://cdn.amcharts.com/lib/4/themes/animated.js", async: true, defer: true},
]
}
}
</script>
InstanceCreationForm.vue
:
<template>
<main-template>
<template v-slot:content>
<router-link to="/" id="cancel-button" type="button">
<i class="ti-trash"></i> Cancel
</router-link>
</template>
</main-template>
</template>
<script>
import MainTemplate from "@/components/MainTemplate.vue";
export default {
name: "InstanceCreationForm",
components: {MainTemplate},
extends: MainTemplate,
}
</script>
I could solve the problem by using anchor tags (<a>
) to redirect between routes, but it feels inefficient to reload the entire page every time the user moves pages. The only other solution I could find was either force reloading my component on page load which effectively does the same thing.
Why aren't my JavaScript packages loading on vue-router
redirect?
I found the answer!
The solution was to add the library as a <src>
tag after the component has mounted:
MainTemplate.vue
import "../js/vendors.min.js"
import "../assets/icons/feather-icons/feather.min.js"
import "../assets/vendor_components/apexcharts-bundle/dist/apexcharts.js"
import "../js/demo.js"
import "../js/jquery.smartmenus.js"
import "../js/menus.js"
import "../js/template.js"
export default {
name: "MainTemplate",
methods: {
loadLibrary(libraryPath) {
let newScript = document.createElement('script')
newScript.setAttribute('src', libraryPath)
document.head.appendChild(newScript)
}
},
mounted() {
if (this.$options.name === 'MainTemplate') {
this.loadLibrary("/src/js/vendors.min.js")
this.loadLibrary("/src/assets/icons/feather-icons/feather.min.js")
this.loadLibrary("/src/assets/vendor_components/apexcharts-bundle/dist/apexcharts.js")
this.loadLibrary("/src/js/demo.js")
this.loadLibrary("/src/js/jquery.smartmenus.js")
this.loadLibrary("/src/js/menus.js")
this.loadLibrary("/src/js/template.js")
}
}
}
I chose to put this code in my MainTemplate (because my other components extend from it) rather than use it in each one.
I also kept my original import statements so that they run the first time the site is loaded.