Is there any way to change default value of a prop in a vuetify component?
For example lets say we have a component like v-btn.
This component has many props, One of them like outlined with default value of false.
Lets say i want is to change this default value to true forever in my application. Is there any way?
I was able to do that at the top of my app's entry point (before any Vue component creation).
/**
* [required imports]
* (you must somehow import VBtn component separately)
*/
Vue.use(Vuetify);
VBtn.options.props.outlined.default = true;
But this practice is called monkey patching and not encouraged to use, consider to use inheritance instead.
In my case I was trying to get component from Vue.options.components['VBtn'] but it didn't work.
So I monkey patched vue library too:
import Vue from "vue";
import Vuetify from 'vuetify'
export const vueComponentsImported: any = {};
export const vueComponentFnDefault = Vue.component.bind(Vue);
/** #see node_modules/vue/src/core/global-api/assets.js */
export const vueComponentFnModded = (id, component) => {
vueComponentsImported[id] = component;
return vueComponentFnDefault(id, component);
};
Vue.component = vueComponentFnModded;
Vue.use(Vuetify);
let VBtn = vueComponentsImported['VBtn'];
if (VBtn) {
VBtn.options.props.outlined.default = true;
}
(please feel free to edit this code if it doesn't work, I have much more lines in my app)
It doesn't make sense to do this,you could just replace '<v-btn' with '<v-btn outlined'.
Related
from nuxt 3 documentation,
https://nuxt.com/docs/getting-started/state-management
I'm told that I should never define ref outside script setup
since it will "be shared across all users visiting your website and can lead to memory leaks!"
I want to use vueuse's useBreakpoints,
https://vueuse.org/core/useBreakpoints/
I simply put them in composable and export,
and happily use them all across components.
but I see their type is globalThis.Ref
is it safe to use them as is,
or am I in big trouble as nuxt doc says?
// file: composables/useMedia.ts
import { breakpointsTailwind, useBreakpoints } from '#vueuse/core'
const breakpoints = useBreakpoints(breakpointsTailwind)
export const isDesktop = breakpoints.greaterOrEqual('lg')
export const isTablet = breakpoints.greaterOrEqual('sm') && breakpoints.smaller('lg')
export const isMobile = breakpoints.smaller('sm')
this is closely related to vue's response system
you don't need to worry about memory leaks when using compiler tools like nuxi
however here another problem is that react system cannot determine the dependencies and when to unmount. if you want to declare once and use globally use pinia otherwise use this code:
import { breakpointsTailwind, useBreakpoints } from '#vueuse/core'
export function useMedia() {
const breakpoints = useBreakpoints(breakpointsTailwind)
const isDesktop = breakpoints.greaterOrEqual('lg')
const isTablet = breakpoints.greaterOrEqual('sm') && breakpoints.smaller('lg')
const isMobile = breakpoints.smaller('sm')
return { isDesktop, isTable, isMobile }
}
and use
const { isDesktop } = useMedia()
note: your code doesn't react when changing the values. if you need response use computed
I"m porting my new app from vue2 to vue3. Since mixins are not recommended way of reusing code in vue3, Im trying to convert them into composable.
I've 2 mixins (methods) __(key) and __n(key, number) in mixins/translate.js which will translate any word into the app's locale.
module.exports = {
methods: {
/**
* Translate the given key.
*/
__(key, replace = {}) {
// logic
return translation
}
Now this is how I converted it as
Composables/translate.js
export function __(key, replace = {}) {
// logic
return translation
}
and since I need these functions to be accessbile in every component without explicitly importing. I'm importing it in app.js
import {__, __n} from '#/Composables/translate.js';
Questions
__() is not accessible in every component. How to make this function accessible in every component without explicit import
Is this the right of doing things?
These functions are required essentially in every component, declaring them in every component is impractical.
#1, You can put it into the globalProperties object
import {__, __n} from '#/Composables/translate.js';
const app = createApp(AppComponent);
app.config.globalProperties.__ = __;
app.config.globalProperties.__n = __n;
#2, though opinion based, importing for every component that needs it would be my preferred way.
I use Vue 3 and I have a dynamic component. It takes a prop called componentName so I can send any component to it. It works, kind of.
Part of the template
<component :is="componentName" />
The problem is that I still need to import all the possible components. If I send About as a componentName I need to import About.vue.
Part of the script
I import all the possible components that can be added into componentName. With 30 possible components, it will be a long list.
import About "#/components/About.vue";
import Projects from "#/components/Projects.vue";
Question
It there a way to dynamically import the component used?
I already faced the same situation in my template when I tried to make a demo of my icons which are more than 1k icon components so I used something like this :
import {defineAsyncComponent,defineComponent} from "vue";
const requireContext = require.context(
"#/components", //path to components folder which are resolved automatically
true,
/\.vue$/i,
"sync"
);
let componentNames= requireContext
.keys()
.map((file) => file.replace(/(^.\/)|(\.vue$)/g, ""));
let components= {};
componentNames.forEach((component) => { //component represents the component name
components[component] = defineAsyncComponent(() => //import each component dynamically
import("#/components/components/" + component + ".vue")
);
});
export default defineComponent({
name: "App",
data() {
return {
componentNames,// you need this if you want to loop through the component names in template
};
},
components,//ES6 shorthand of components:components or components:{...components }
});
learn more about require.context
welcome to this topic. i recently tried to use the Nuxt framework to make my web-application but i ran into a problem.
In my default layout i have two components. a header component and a sidebar component. if i click on the hamburger icon in the header component the sidebar needs to get smaller or bigger depending on the hamburger icon state (true or false)
so to make it more complicated i don't want to use a prop to send it through the other component. i want to make it as a template so people can use it easy. can i transform a local component variable to a global variable other components can use?
so the code i have now is like this:
this is the index page
this is the header component
this is the sidebar component
as you can see i trigger the hamburgerstate on the header component page.
i want to access that state in the sidebarcomponent to so i can adjust the sidebar
the one thing that's IMPORTANT is that it needs to be as simple as possible so people who use this template later don't have to add unnecessary work
any possibilities this can work?
The simplest way to achieve a global variable is to set it as a state element and have a mutation for changing it. As your 'hambuger' is a boolean there is no need to pass parameters to the mutation making it all the easier.
You may want to have a named module in you store to handle this but I'll just put it in store/index.js for now.
export const state = () => ({
hamburger: true
})
export const mutations = {
changeHamburger (state) {
state.hamburger = !state.hamburger
}
}
Then in any page or component you can access that state element:
Component.vue
<script>
import { mapMutations } from 'vuex'
export default {
computed: {
hamburger () {
return this.$store.state.hamburger
}
},
methods: {
...mapMutations({
hamburgerChange: 'changeHamburger'
})
}
}
</script>
So this means you can now use the computed property 'hamburger' in your component and can change it by calling 'hamburgerChange', eg <v-btn #click="hamburgerChange">.
I want to create a custom Vue directive that lets me select components on my page which I want to hydrate. In other words, this is what I want to archive
I render my Vue app on the server (ssr)
I attach a directive to some components, like this:
<template>
<div v-hydrate #click="do-something"> I will be hydrated</div>
</template>
I send my code to the client and only those components that have the v-hydrate property will be hydrated (as root elements) on the client.
I want to achieve this roughly this way:
I will create a directives that marks and remembers components:
import Vue from "vue";
Vue.directive("hydrate", {
inserted: function(el, binding, vnode) {
el.setAttribute("data-hydration-component", vnode.component.name);
}
});
My idea is that in my inserted method write a data-attribute to the server-rendered element that I can read out in the client and then hydrate my component with.
Now I have 2 questions:
Is that a feasible approach
How do I get the component name in el.setAttribute? vnode.component.name is just dummy code and does not exist this way.
PS: If you want to know why I only want to hydrate parts of my website: It's ads. They mess with the DOM which breaks Vue.
I could figure it out:
import Vue from "vue";
Vue.directive("hydrate", {
inserted: function(el, binding, vnode) {
console.log(vnode.context.$options.name); // the component's name
}
});
I couldn't get the name of my single file components using the previously posted solution, so I had a look at the source code of vue devtools that always manages to find the name. Here's how they do it:
export function getComponentName (options) {
const name = options.name || options._componentTag
if (name) {
return name
}
const file = options.__file // injected by vue-loader
if (file) {
return classify(basename(file, '.vue'))
}
}
where options === $vm.$options