Componentes
David Daza
Full Stack Developer - Datasketch
@ddazal
@_daviddaza
Lugar · Bebidas · Comida
Las interfaces de usuario pueden ser divididas en componentes
Barra de navegación
Footer
Carousel
Card
Card
Card
Card
Card
Sidebar
Las interfaces de usuario pueden ser abstraídas en un árbol de componentes
Vue.component('welcome', {
template: '<h1>Welcome</h1>'
})
new Vue({
el: '#app'
})<div id="app">
<welcome></welcome>
<!-- <welcome /> -->
<!-- <Welcome></Welcome> -->
<!-- <Welcome /> -->
</div>const Welcome = {
template: '<h1>Welcome</h1>'
}
new Vue({
el: '#app',
components: { Welcome }
})<div id="app">
<Welcome />
</div>Vue.component('welcome', {
props: ['name'],
template: '<h1>Welcome, {{ name }}</h1>'
})
new Vue({
el: '#app',
data() {
return {
name: 'babies'
}
}
})<div id="app">
<Welcome :name="name" />
</div>Vue.component('welcome', {
props: {
name: {
type: String,
default: 'stranger',
// required: true
// validator(val) { return val.length > 1}
}
},
template: '<h1>Welcome, {{ name }}</h1>'
})
new Vue({
el: '#app',
data() {
return {
name: 'babies'
}
}
})✅ Los componentes son bloques independientes y reutilizables de una interfaz
✅ Los componentes reciben datos mediante la propiedad props
✅ data debe ser una función
✅ Un solo elemento raíz por componente
Padre
Hijo
pasa props
emite eventos
const Counter = {
props: {
count: Number
},
template: `<button @click="increment">{{ count }}</button>`,
methods: {
increment() {
this.$emit('increment')
}
}
}
new Vue({
el: '#app',
components: { Counter },
data() {
return {
count: 0
}
},
methods: {
incrementCount() {
this.count += 1
}
}
})<div id="app">
<Counter :count="count" @increment="incrementCount"/>
</div>const Counter = {
props: {
count: Number
},
template: `<button @click="increment">{{ count }}</button>`,
methods: {
increment() {
this.$emit('increment', 2)
}
}
}
new Vue({
el: '#app',
components: { Counter },
data() {
return {
count: 0
}
},
methods: {
incrementCount(factor) {
this.count += factor
}
}
})Vue.component('MouseTracker', {
props: {
pos: Object,
},
template: `
<div class="mouse-tracker" @mousemove="$emit('track', $event)">
</div>
`
})
new Vue({
el: '#app',
data() {
return {
pos: { x: 0, y: 0 },
}
},
methods: {
updatePosition(event) {
this.pos.x = event.clientX
this.pos.y = event.clientY
}
}
})✅ Los hijos pueden emitir eventos a sus padres utilizando el método $emit
✅ Los props no deben ser modificados por el componente que los recibe, sino por el componente padre
✅ Para acceder al objeto Event, emite el evento con la variable $event
<input v-model="text" />
<input :value="text" @input="text = $event.target.value" />
✅ Enlazar el atributo value a un prop value
✅ Emitir el evento input con el nuevo valor
Vue.component('my-search', {
props: ['value'],
template: `
<div class="my-search">
<input type="text" placeholder="Search" :value="value" @input="$emit('input', $event.target.value)"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></svg>
</div>
`
})
new Vue({
el: '#app',
data() {
return {
search: ''
}
}
})<div id="app">
<my-search v-model="search"></my-search>
</div>✅ beforeCreate
✅ created
✅ beforeMount
✅ mounted
✅ beforeUpdate
✅ updated
✅ beforeDestroy
✅ destroyed
Es llamado antes de que la instancia pueda observar los datos y configurar eventos
La instancia configura los datos, computed properties, métodos, watch/event callbacks.
$el está disponible
Se hace render del DOM
Es llamado cuando cambian los datos, pero antes de actualizar el DOM
Es llamado cuando el DOM se ha actualizado con el cambio de los datos
Es llamado justo antes de destruir la instancia/componente
El componente ha sido eliminado totalmente
<div class="notification">
<div class="notification-body">
<p>Account verified</p>
<div class="notification-dismiss">
<button>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zM11.4 10l2.83-2.83-1.41-1.41L10 8.59 7.17 5.76 5.76 7.17 8.59 10l-2.83 2.83 1.41 1.41L10 11.41l2.83 2.83 1.41-1.41L11.41 10z"/></svg>
</button>
</div>
</div>
</div><div class="notification">
<div class="notification-body">
<slot></slot>
<div class="notification-dismiss">
<button>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zM11.4 10l2.83-2.83-1.41-1.41L10 8.59 7.17 5.76 5.76 7.17 8.59 10l-2.83 2.83 1.41 1.41L10 11.41l2.83 2.83 1.41-1.41L11.41 10z"/></svg>
</button>
</div>
</div>
</div>Vue.component('notification', {
template: `
<div class="notification">
<div class="notification-body">
<slot></slot>
<div class="notification-dismiss">
<button>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zM11.4 10l2.83-2.83-1.41-1.41L10 8.59 7.17 5.76 5.76 7.17 8.59 10l-2.83 2.83 1.41 1.41L10 11.41l2.83 2.83 1.41-1.41L11.41 10z"/></svg>
</button>
</div>
</div>
</div>
`
})
new Vue({
el: '#app'
})<div id="app">
<notification>
<p>Account verified!</p>
</notification>
</div><div class="modal">
<div class="modal-header">
<button>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zM11.4 10l2.83-2.83-1.41-1.41L10 8.59 7.17 5.76 5.76 7.17 8.59 10l-2.83 2.83 1.41 1.41L10 11.41l2.83 2.83 1.41-1.41L11.41 10z"/></svg>
</button>
</div>
<div class="modal-body">
<h3 class="modal-title">Payment successful!</h3>
<p class="modal-content">Thank you for shopping with us! We are lucky to have customers like you so your order will be as soon as possible in your door ❤️</p>
</div>
<div class="modal-footer">
<button>Done</button>
</div>
</div><div class="modal">
<div class="modal-header">
<button>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zM11.4 10l2.83-2.83-1.41-1.41L10 8.59 7.17 5.76 5.76 7.17 8.59 10l-2.83 2.83 1.41 1.41L10 11.41l2.83 2.83 1.41-1.41L11.41 10z"/></svg>
</button>
</div>
<div class="modal-body">
<h3 class="modal-title"><slot name="title"></slot></h3>
<p class="modal-content"><slot name="content"></slot></p>
</div>
<div class="modal-footer">
<button><slot name="cta"></slot></button>
</div>
</div>Vue.component('my-modal', {
template: `
<div class="modal">
<div class="modal-header">
<button>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zM11.4 10l2.83-2.83-1.41-1.41L10 8.59 7.17 5.76 5.76 7.17 8.59 10l-2.83 2.83 1.41 1.41L10 11.41l2.83 2.83 1.41-1.41L11.41 10z"/></svg>
</button>
</div>
<div class="modal-body">
<h3 class="modal-title"><slot name="title"></slot></h3>
<p class="modal-content"><slot name="content"></slot></p>
</div>
<div class="modal-footer">
<button><slot name="cta"></slot></button>
</div>
</div>
`
})
new Vue({
el: '#app'
})<div id="app">
<my-modal>
<template v-slot:title>
Payment successful!
</template>
<template v-slot:content>
Thank you for shopping with us! We are lucky to have customers like you so your order will be as soon as possible in your door ❤️
</template>
<template v-slot:cta>
Done
</template>
</my-modal>
</div><div id="app">
<my-modal>
<template #title>
Payment successful!
</template>
<template #content>
Thank you for shopping with us! We are lucky to have customers like you so your order will be as soon as possible in your door ❤️
</template>
<template #cta>
Done
</template>
</my-modal>
</div><div id="app">
<my-modal>
<template slot="title">
Payment successful!
</template>
<template slot="content">
Thank you for shopping with us! We are lucky to have customers like you so your order will be as soon as possible in your door ❤️
</template>
<template slot="cta">
Done
</template>
</my-modal>
</div>Vue.component('user-card', {
template: `
<div>
<slot>{{ user.firstname }} {{ user.lastname }} is {{ user.status }}</slot>
</div>`,
data() {
return {
user: {
firstname: 'Jane',
lastname: 'Doe',
status: 'connected'
}
}
}
})
new Vue({
el: '#app'
})<div id="app">
<user-card></user-card>
</div><div id="app">
<user-card>
Yes! {{ user.firstname }} is {{ user.status }}
</user-card>
</div>Vue.component('user-card', {
template: `
<div>
<slot v-bind:user="user">{{ user.firstname }} {{ user.lastname }} is {{ user.status }}</slot>
</div>`,
data() {
return {
user: {
firstname: 'Jane',
lastname: 'Doe',
status: 'connected'
}
}
}
})
new Vue({
el: '#app'
})<div id="app">
<user-card v-slot="slotProps">
Yes! {{ slotProps.user.firstname }} is {{ slotProps.user.status }}
</user-card>
</div><div id="app">
<user-card v-slot="{ user }">
Yes! {{ user.firstname }} is {{ user.status }}
</user-card>
</div>Vue.component('tab-home', {
template: '<div>Home component</div>'
});
Vue.component('tab-posts', {
template: '<div>Posts component</div>'
});
Vue.component('tab-archive', {
template: '<div>Archive component</div>'
});
new Vue({
el: '#app',
data: {
currentTab: 'Home',
tabs: ['Home', 'Posts', 'Archive']
},
computed: {
currentTabComponent: function() {
return 'tab-' + this.currentTab.toLowerCase();
}
}
});<div id="app">
<button v-for="tab in tabs" :class="['tab-button', { active: currentTab === tab }]" @click="currentTab = tab">
{{ tab }}
</button>
<component v-bind:is="currentTabComponent" class="tab"></component>
</div>@ddazal
@_daviddaza