import { debounce } from 'radash';
const onInput = (event) => {
console.log('onInput event', event);
}
const debouncedInput = debounce({ delay: debounceBy.value }, onInput);
<form
@input.prevent="debouncedInput"
>
<!-- ... -->
</form>
import { debounce } from 'radash';
const onInput = (event) => {
console.log('onInput event', event);
}
const debouncedInput = debounce({ delay: debounceBy.value }, onInput);
<form
@input.prevent="debouncedInput"
>
<!-- ... -->
</form>
<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
<template>
<template
v-if="!slots.default"
>
<button type="button">button</button>
</template>
<template v-else>
<button type="button"><slot/></button>
</template>
</template>
Para acessar slots e atributos (attrs) usando a Composition API no Vue.js, você precisa entender como a função setup
funciona e como ela fornece acesso ao contexto do componente. A Composition API introduziu uma nova maneira de acessar e manipular slots e atributos, diferente da Options API, que usava o objeto this
para acessar esses recursos.
Na Composition API, o contexto do componente, que inclui slots e atributos, é passado como o segundo argumento para a função setup
. Você pode acessar slots e atributos diretamente através desse objeto de contexto. Aqui estão exemplos de como fazer isso:
export default {
setup(props, context) {
console.log(context.slots);
console.log(context.attrs);
}
}
export default {
setup(props, { slots, attrs }) {
console.log(slots);
console.log(attrs);
}
}
Os slots são espaços reservados em um componente Vue.js que permitem que o conteúdo seja passado de um componente pai para um componente filho. Eles são definidos dentro do bloco <template>
de um componente Vue.js e podem ser usados para injetar conteúdo dinâmico.
<!-- MyButton.vue -->
<template>
<button>
<slot></slot>
</button>
</template>
<!-- Parent of button -->
<template>
<my-button>
This is going to be placed where the slots are <b>Also accept HTML and components</b>
</my-button>
</template>
Para componentes que usam a sintaxe <script setup>
, a Composition API fornece composables useSlots
e useAttrs
para acessar slots e atributos.
<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
A Composition API oferece uma maneira poderosa e flexível de acessar e manipular slots e atributos em componentes Vue.js. Ao usar a função setup
e os composables useSlots
e useAttrs
, você pode criar componentes mais dinâmicos e reutilizáveis, aproveitando ao máximo os recursos do Vue.js [1][2][3][4][5].
Citations: [1] https://dev.to/zelig880/how-to-use-slots-and-attrs-with-the-composition-api-k75 [2] https://learnvue.co/articles/vue-context-argument [3] https://stackoverflow.com/questions/60202724/vue-3-composition-api-and-access-to-vue-instance [4] https://vuejs.org/api/composition-api-setup.html [5] https://vuejs.org/guide/components/slots.html [6] https://doc.vueframework.com/api/composition-api.html [7] https://vue-community.org/vue/comprehensive-guide-to-vue-js-slots-mastering-component-composition.html [8] https://www.stackovercloud.com/2021/12/03/how-to-make-your-vue-js-application-dry-with-slots-mixins-and-composition-api/ [9] https://v2.vuejs.org/v2/guide/components-slots.html [10] https://markus.oberlehner.net/blog/context-and-provider-pattern-with-the-vue-3-composition-api/ [11] https://www.webmound.com/vue-context-argument-composition-api-script-setup/ [12] https://vuejs.org/guide/extras/render-function.html [13] https://www.nightprogrammer.com/vue-3/how-to-use-slots-in-composition-api-in-vue-js-3-example/ [14] https://staging-cf.vuejs.org/guide/components/slots [15] https://medium.com/dana-engineering/complete-guide-vue-3-composition-api-284e19ee0831
<template>
<div>
<p>Count: {{ count }}</p>
<!-- <ChildComponent /> -->
</div>
</template>
<script lang="ts">
import { computed, defineComponent, provide } from 'vue'
// import ChildComponent from './ChildComponent.vue'
export default defineComponent({
components: {
// ChildComponent,
},
setup() {
const count = computed(() => {
return 1 + 1
})
provide('count', count)
return {
count,
}
},
})
</script>
// so-carrao-projetos/the-spa/components/molecules/ecommerce/AdvertisementStepper.vue
export default {
name: 'AdvertisementStepper',
components: {
StepOne: () => import(/* webpackMode: "eager" */'@/components/molecules/ecommerce/steps/StepOne'),
StepTwo: () => import(/* webpackMode: "eager" */'@/components/molecules/ecommerce/steps/StepTwo'),
StepThree: () => import(/* webpackMode: "eager" */'@/components/molecules/ecommerce/steps/StepThree'),
StepFour: () => import(/* webpackMode: "eager" */'@/components/molecules/ecommerce/steps/StepFour'),
StepFive: () => import(/* webpackMode: "eager" */'@/components/molecules/ecommerce/steps/StepFive')
},
// ...
}
// resources/js/Components/Icons/icons.js
/*
// Usage:
app.use(loadIcons())
*/
import EyeIcon from '@/Components/Icons/EyeIcon.vue';
import EyeSlashIcon from '@/Components/Icons/EyeSlashIcon.vue';
export const loadIcons = () => {
return {
install(app, options) {
app
.component('EyeIcon', EyeIcon)
.component('EyeSlashIcon', EyeSlashIcon);
},
}
}
Here's an example of a Vue.js plugin that provides both global functions and directives. This plugin exposes a $hello()
function and a v-my-directive
directive.
// extra/plugins/AppExtra/index.js
const toJson = function (...params) {
return JSON.stringify(...params);
};
const AppExtra = {
install(app, options) {
const methods = {
toJson,
}
app.mixin({
methods: methods,
});
if (parseInt(app.version) > 2) {
Object.entries(methods).forEach(item => {
let [name, func] = item;
app.provide(name, func);
})
}
// Global function
app.config.globalProperties.$toJson = toJson;
// Global directive
app.directive('extra-data', {
beforeMount(el, binding, vnode, prevVnode) {
// el.textContent = binding.value;
el.setAttribute('data-extra', JSON.stringify(binding.value));
},
updated(el, binding, vnode, prevVnode) {
el.setAttribute('data-extra', JSON.stringify(binding.value));
// el.textContent = binding.value;
},
});
},
};
export default AppExtra;
To use this plugin, you would import it and call app.use()
in your Vue app's initialization:
// main.js
import { createApp } from 'vue';
import AppExtra from '@/extra/plugins/AppExtra';
const app = createApp({});
app.use(AppExtra);
app.mount('#app');
Now, you can use the $hello()
function and v-my-directive
directive in your components:
<!-- App.vue -->
<template>
<div>
<p v-extra-data="{abc: 'def', ghi: 123, xyz: true}"></p>
<h1>{{ $toJson({abc: 'def', ghi: 123, xyz: true}) }}</h1>
<h1>{{ toJson({abc: 'def', ghi: 123, xyz: true}) }}</h1>
</div>
</template>
This example demonstrates how to create and use a simple plugin that provides both global functions and directives. You can extend this plugin to include more functionality as needed.
For more information, you can refer to the following resources:
<script setup lang="js">
const vMyDirective = {
beforeMount: (el) => {
el.innerText = el.innerText.toUpperCase();
}
}
</script>
<span v-my-directive>algo aqui para teste</span>
// myDirective.js
export const myDirective = {
beforeMount: (el) => {
el.innerText = el.innerText.toUpperCase();
}
}
<script setup lang="js">
import { myDirective as vMyDirective } from './myDirective.js'
</script>
<span v-my-directive>algo aqui para teste</span>
<!--
Resultado:
<span>ALGO AQUI PARA TESTE</span>
-->
// resources/js/plugins/lang.js
import { lang } from '@/helpers/localization';
// Criação do plugin
export const LangPlugin = {
install(app, options) {
const _lang = (...params) => lang(...params);
app.mixin({
methods: {
lang: _lang,
},
});
if (parseInt(app.version) > 2) {
app.provide('lang', _lang);
}
},
};
// resources/js/app.js
import { LangPlugin } from '@/plugins/lang';
// ...
createApp(...)
.use(LangPlugin)
// ...
import { router } from "@inertiajs/vue3";
router.visit(route('dashboard', ['aaa', { tab: e }])); // { tab: '1' } is the query parameter
<script>
import { router } from "@inertiajs/vue3";
const handleTabChange = (tab) => {
let userId = 1;
router.visit(route('dashboard', [ // .../dashboard?abc=&tab=tab1&user=1
'abc',
{ tab: tab },
{ user: userId },
])
);
}
</script>
<template>
<button
type="button"
@click="handleTabChange('tab1')"
>Go to tab1</button>
</template>
3 Ways to Persist Pinia State (on local storage)