Browsers: Chrome 75.0.3770.142
OS: Mac OS 10.14.6
Storing the imported icon value in the component data has several effects. It assumes that we are not making a functional component and it gives the variable storing the icon svg data reactivity to changes which are never going to happen.
The svg data for icons should be static and non-reactive. Every attempt should be made to eliminate any data or computational overhead with icons. We shouldn't just try to make the payload smaller, we should also make it efficient with how it's used.
The example places the icon svg data into the component's data object. Vue will then add watchers to this data which shouldn't change in most use cases, adding additional overhead to the component. The means that if the component is making use of many icons, its making many watchers.
https://vuetifyjs.com/en/customization/icons#install-material-design-icons-js-svg
This is what is in the example:
<!-- Vue Component -->
<template>
<v-icon>{{ svgPath }}</v-icon>
</template>
<script>
import { mdiAccount } from '@mdi/js'
export default {
data: () => ({
svgPath: mdiAccount
}),
}
</script>
Do you have a proposed solution for this?
Possibly something like this. https://stackoverflow.com/a/45815401/2719773
Or in other words:
<!-- Vue Component -->
<template>
<v-icon>{{ $icons.mdiAccount }}</v-icon>
</template>
<script>
import { mdiAccount } from '@mdi/js'
export default {
created () {
this.$icons = { mdiAccount }
}
}
</script>
But I'm not sure if this is the best solution.
hmmm then in that case maybe it should just be defined at boot strapping
https://vuetifyjs.com/en/customization/icons#using-custom-icons
Well, it depends on what we want to do. Do I want to load in all of the icons at once on first load? Or do I want to load the icons in on an as needed basis through webpackChunks? I wish there was a simple way to do it that checks all the boxes.
well what im saying is something like this.
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
import { mdiAccount } from '@mdi/js'
Vue.use(Vuetify)
export default new Vuetify({
icons: {
iconfont: 'mdiSvg',
values: {
account: mdiAccount,
},
},
})
// component.vue
<!-- Vue Component -->
<template>
<v-icon>$vuetify.icons.account</v-icon>
</template>
<script>
export default {
data: () => ({}),
}
</script>
but i see what you are saying, that would be an instance of global/all at once, for a single instance basis the other would probably work better, though I'm no expert of overhead. Can you confirm if either (or both) solutions work to what you are describing?
If so can update the examples to provide a clearer global vs singular in conjunction with the update for #6033 as the whole icon page imo need a nice overhaul
Yes, I understand. But wouldn't that mean that all of the icons you have imported into the vuetify plugin file will be part of the initial payload of your application? What if you didn't want to do that? What if you wanted to have the icons in different chunk files so the initial payload is kept lean?
Perhaps I'm just being way to picky, or I am misunderstanding how webpack chunking works. But from my perspective if we are trying to be as lean as possible by using @mdi/js then we should assume that we want that to translate to how the icons get loaded in as well.
I can confirm that doing this:
export default {
created () {
this.$icons = { mdiAccount }
}
}
works. I have not tried the global way of doing it though.
you can also Object.freeze()
My two cents on this one (after one year).
I think a computed property would be the most suited option. Here's the pattern I use :
<template>
<v-icon>{{icons.mdiAccount}}</v-icon>
</template>
import { mdiAccount } from '@mdi/js'
...
computed: {
icons: () => ({
mdiAccount
})
}
But I wish there was some kind of smart loader that can automatically detect the used svg icons and import them, without having to do all the hassle to import and define them as properties to use them in the templates, and also avoiding a big initial payload.
Most helpful comment
well what im saying is something like this.