Para iniciar Vue podemos utilizarlo a través de un CDN o añadiendo el archivo físicamente. Aquí empezarémos a utilizarlo a través de CDN. El enlace del CDN puede variar con el tiempo, pero cuando escribo este Gist es el siguiente:
https://cdn.jsdelivr.net/npm/vue/dist/vue.js
Creamos un archivo html
y añadimos el CDN:
/index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
</body>
</html>
Una vez creado el html con el script del CDN, inicializamos un script con una nueva instancia de Vue. Vamos a llamar al elemento app
:
new Vue({
el: '#app',
});
Estamos que debemos de crear un div
con el id app
para que se inicialice dentro Vue.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
</div>
<script>
new Vue({
el: '#app',
});
</script>
</body>
</html>
Vamos a inicializar el método data
donde guardaremos variables y podrémos utilizar a través de interpolación. Vamos a crear un mensaje Hola mundo
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{ message }}
</div>
<script>
new Vue({
el: '#app',
data() {
return {
message: 'Hola Mundo',
}
}
});
</script>
</body>
</html>
Lo más correcto es tener todo en distintos archivos modularizados, lo que llamamos en Vue componentes
. Así que vamos a crear un archivo en la misma carpeta llamado components
y vamos a llamarlo por ejemplo message.js
(cuando utilicemos el CLI de Vue usaremos la extensión .vue, pero como usamos la versión de CDN es mejor usar .js).
Los archivos quedarían de la siguiente manera:
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
</head>
<body>
<div id="app">
<message></message>
</div>
<script>
new Vue({
el: '#app',
});
</script>
</body>
</html>
/components/message.js
Vue.component('message', {
data() {
return {
message: 'Hola Mundo',
}
},
template: `
<div>
<h2>Componente message</h2>
<p>{{ message }}</p>
</div>
`
});
- Cada template tendrá que tener un contenedor padre.
- Los componentes deben estar antes que la instancia de Vue.
Nos permiten crear nuevas propiedades reactivas que dependen de otra propiedades del objeto data
y que pueden tener una lógica "complicada" (filtros, concatenaciones, etc).
Un ejemplo de computed properties sería el siguiente:
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
</div>
<script>
new Vue({
el: '#app',
});
</script>
</body>
</html>
Hemos añadido un script
con computed-properties
y añadido el tag con el mismo nombre <computed-properties></computed-properties>
Después añadimos el componente, con una data
, un computed
con los elementos a mostrar del data
y un template
:
/components/computed-properties.js
Vue.component('computed-properties', {
data() {
return {
name: 'José Luis',
surname: 'García'
}
},
computed: {
fullName() {
return `${this.name} ${this.surname}`;
},
},
template: `
<div>
<h2>Computed properties</h2>
<p>{{ fullName }}</p>
</div>
`
});
Para escribir métodos utilizaremos la palabra methods
y ahí meteremos los elementos que queramos.
En el siguiente ejemplo vemos como implementamos methods
:
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
</div>
<script>
new Vue({
el: '#app',
});
</script>
</body>
</html>
Y el componente es el siguiente:
/components/methods.js
Vue.component('methods', {
data() {
return {
name: 'José Luis',
surname: 'García'
}
},
computed: {
fullName() {
return `${this.name} ${this.surname}`;
}
},
methods: {
hello() {
alert(this.fullName);
}
},
template: `
<div>
<h2>Ejecutar métodos con Vuejs</h2>
<p @click="hello">Pulsa aquí para ejecutar el método hello</p>
</div>
`
});
El evento v-on:click
es igual que @click
es un atajo.
Es una forma de actualizar datos tanto en la template como en el script, que sean de ida y vuelta. Son muy útiles cuando utilizamos formularios.
La directiva v-model
espera un dato, en este caso espera el dato framework
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
</div>
<script>
new Vue({
el: '#app',
});
</script>
</body>
</html>
/components/vmodel.js
Vue.component('vmodel', {
data() {
return {
framework: 'Vuejs2',
}
},
template: `
<div>
<h2>Trabajando con vmodel</h2>
<input v-model="framework" />
<p>El framework usado es {{ framework }}</p>
</div>
`
})
Un ejemplo de v-model
con formulario y array es el siguiente:
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
</div>
<script>
new Vue({
el: '#app',
});
</script>
</body>
</html>
/components/vmodel-checkboxes.js
Vue.component('vmodel-checkboxes', {
data() {
return {
frameworks: [],
}
},
template: `
<div>
<h2>Vmodel con arrays</h2>
<input type="checkbox" id="vuejs2" value="Vuejs2" v-model="frameworks" />
<label for="vuejs2">Vuejs 2</label>
<input type="checkbox" id="reactjs" value="Reactjs" v-model="frameworks" />
<label for="reactjs">Reactjs</label>
<input type="checkbox" id="angular" value="Angular" v-model="frameworks" />
<label for="angular">Angular</label>
<p>Frameworks seleccionados: {{ frameworks }}</p>
</div>
`
});
Los eventos siempre se emiten del elemento hijo al elemento padre (de abajo hacia arriba). Para entender esto tenemos el siguiente ejemplo:
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
</div>
<script>
new Vue({
el: '#app',
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Vemos que utilizamos el componente <emit>
el cual le pasamos un evento v-on
con @
con el nombre @show_card_brand
y le pasamos un método. En la misma página añadimos el método con el alert
.
/components/emit.js
Vue.component('emit', {
data() {
return {
carBrand: 'Tesla',
}
},
template: `
<div>
<h2>Emitir eventos Vuejs2</h2>
<p @click="$emit('show_car_brand', carBrand)">Pulsa aquí para emitir un evento a la instancia ROOT de VueJS</p>
</div>
`
});
$emit
nos permite pasar dos cosas, el primero es el evento que queremos emitir y el segundo el dato le queremos pasar cuando pasemos el evento: <p @click="$emit('show_car_brand', carBrand)">Texto</p>
En el index.html
inyectamos el script del componente y ponemos la etiqueta del component en este caso parent-data
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Aquí creamos un archivo llamado parent-data.js
donde pondrémos una template accediendo al dato que queremos. Usamos $parent
para acceder al elemento de arriba (padre). Si queremos subir niveles hacia arriba, usuariamos $parent
las veces que quisieramos. Para subir por ejemplo tres niveles usuariamos $parent.$parent.$parent
. El ejemplo del componente es el siguiente:
/components/parent-data.js
Vue.component('parent-data', {
template: `
<div>
<h2>Acceso a los datos del CMP padre desde el CMP hijo</h2>
{{ $parent.appName }}
</div>
`
});
Creamos una referencia en nuestro componente, en este caso se llama <child-data>
y la referencia se puede llamar como quieras, en el ejemplo le hemos llamado ref="childData"
. En el ciclo de vida de Vue, vamos a poner los datos del componente cuando esté mounted
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Aquí tenemos el cmpName
que deseamos pasar.
/components/child-data.js
Vue.component('child-data', {
data() {
return {
cmpName: 'Child Data CMP',
}
},
template: `
<div>
<h2>Acceso a los datos del CMP hijo desde el CMP padre</h2>
</div>
`
});
Podemos llamar al método primero invocando a nuestro componente child-methods
con la referencia childMethod
. Vamos a poner un ejemplo en el mounted
con un setTimeout
llamándolo de la siguiente manera: this.$refs.childMethod.showCmpName();
Hacemos un ref, despues llamamos al método de la referencia y finalmente el método del hijo.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
</head>
<body>
<div id="app">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
/componentes/.js
Vue.component('child-methods', {
data() {
return {
cmpName: 'Child Data CMP',
}
},
template: `
<div>
<h2>Acceso a métodos del CMP hijo desde el CMP padre</h2>
</div>
`,
methods: {
showCmpName() {
console.log(`Llamada al método showCmpName ${this.cmpName}`);
}
}
});
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Creamos unos datos típicos como son email
y password
. Creamos el método login
donde cambiamos el logged
a true
si la condición this.user.email === 'test@m.com' && this.user.password === 1234
es true
.
La directiva v-show
la utilizamos si queremos mostrar el contenido, en este caso sólo se mostrará si logged
es true
.
Para el formulario utilizamos @submit
que por si sólo hace una redirección. Para evitar esta redirección pondremos @submit.prevent
y en este caso le decimos que haga caso al método login
, quedando de la siguiente manera: <form @submit.prevent="login">
.
v-model
nos permite hacer databinding, que hace que cambie los datos del componente.
/components/login-form.js
Vue.component('login-form', {
data() {
return {
logged: false,
user: {
email: '',
password: ''
}
}
},
methods: {
login() {
this.logged = this.user.email === 'test@m.com' && this.user.password === '1234';
}
},
template: `
<div>
<h2>Formulario de login</h2>
<p v-show="logged" style="background: green; color: #fff;">
Has iniciado sesión con los datos: {{ user }}
</p>
<form @submit.prevent="login">
<input autocomplete="off" type="email" v-model="user.email" name="email"/>
<input type="password" v-model="user.password" name="password" />
<input type="submit" value="Iniciar sesión" />
</form>
</div>
`
});
Nos cubre nuestras necesidades para iterar información. En index.html
sólo habrá que invocar el script y el componente <loops>
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
En el componente creamos un array de Frameworks, después en el template es donde utilizamos el v-for. En el <ul>
usamos la condición v-if
para no mostrar nada si en el array no hay nada guardado.
La directiva v-for
utilizamos si queremos el index
para mostrar el indice. El array se llama frameworks
y por normativa solemos utilizar el elemento para mostrar en singular, así que v-for
quedaría de la siguiente manera: v-for="(framework, index) in frameworks"
. Para que sea clave única y no se repita utilizamos :key
, y le pasamos el elemento framework.id
ya que no se repite.
Dentro del <li>
dibujamos ya toda la información accediendo a través de framework
.
/components/loops.js
Vue.component('loops', {
data() {
return {
frameworks: [
{ id: 1, name: 'Vue2JS' },
{ id: 2, name: 'ReactJS' },
{ id: 3, name: 'Ember' },
{ id: 4, name: 'AdonisJS' },
{ id: 5, name: 'Angular' },
{ id: 6, name: 'Laravel' },
]
}
},
template: `
<div>
<h2>Bucles con v-for</h2>
<ul v-if="frameworks.length">
<li v-for="(framework, index) in frameworks" :key="framework.id">
({{ index }}) | {{ framework.name }}
</li>
</ul>
</div>
`
});
El v-if
lo utilizamos para poder hacer condicionales y mostrar o no datos.
En nuestro index.html
sólo vamos a tener que invocar al componente a través de su archivo js
y después a través de su tag <conditionals>
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Tenemos un dato que es age
y en el input
le decimos que su v-model
de referencia es age
. Ya después hacemos condiciones a traves de la directiva v-if
. Cuando queremos añadir otro elemento usaremos v-else-if
y cuando ya no tengamos que ver ninguna condición añadimos v-else
.
/components/conditionals.js
Vue.component('conditionals', {
data() {
return {
age: 10
}
},
template: `
<div>
<h2>Condicionales con v-if</h2>
<input v-model="age" />
<p v-if="age < 18">Menor de edad</p>
<p v-else-if="age >= 18 && age < 30">Mayor de edad y menor de 30</p>
<p v-else-if="age >= 30 && age < 65">30 años o más y menor de 65</p>
<p v-else>Estás jubilad@</p>
</div>
`
})
Un slot nos permite definir unas layout pero podiendo sobrescribir el contenido.
Después de invocar el js
de nuestro componente y llamarlo por <slot>
meteremos nuestros elementos dentro.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Hacemos el "template" del slot
y a continuación analizamos como se comporta el código.
/components/slots.js
Vue.component('slots', {
template: `
<div>
<h2>Slots, ejemplo de layout</h2>
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</div>
`
});
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
Si nos fijamos en esta parte del código junto a esta:
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
Vemos que si no definimos un <template slot="nameSlot">
realmente nos creará un main, aunque lo creemos en primera instancia. Un slot
lo iremos construyendo según su plantilla y o sino lo llevará a último lugar.
En el index.html
sólo añadimos la ruta del archivo javascript y invocamos al componente que le hemos llamado watchers
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
En watchers
tenemos dos data
de un usuario nuevo user
y de un usuario anterior o viejo oldUser
, los dos sin definir. Después a través de un async
- await
traemos información de un API que nos dá información de usuario aleatoria. Pasamos la información en un JSON
y elegimos sólo la primera opción. Una vez hemos guardado esa información, componemos un usuario a través de su title
, first
y last
.
/components/watchers.js
Vue.component('watchers', {
data() {
return {
user: null,
oldUser: null
}
},
methods: {
async randomUser() {
try {
const data = await fetch('https://randomuser.me/api/');
const json = await data.json();
const user = json.results[0];
this.user = `${user.name.title} ${user.name.first} ${user.name.last}`;
}catch(e) {
//algo ha ido mal
console.log(`Algo ha ido mal: ${e}`);
}
}
},
watch: {
user(newVal, oldVal) {
this.user = newVal;
this.oldUser = oldVal;
}
},
template: `
<div>
<h2>Watchers con VueJS2</h2>
<button @click="randomUser">Obtener un usuario aleatorio</button>
<p>Nuevo usuario: {{ user }}</p>
<p>Anterior usuario: {{ oldUser }}</p>
</div>
`
});
Tenemos el método watch
que es nuestro watcher. Estará viendo el estado de nuestros datos y recogerá lo que queramos. En el watcher
nos va a pedir un newValue
y un oldValue
. Y así en el template, vamos a poder ir recogiendo estos datos y mostrándolos por la pantalla.
En el documento index.html
invocaremos el archivo javascript
de computed-properties-getset.js
e iniciamos el componente llamado <computed-properties-getset>
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Creamos el componente con un dato 0 llamado amount
. Dentro de computed
creamos un amountFormatted
donde tendremos dos funciones llamadas get()
y set()
. Dentro de ellas vamos a poder jugar para tener el valor o poder modificarlo después.
/components/computed-properties-getset.js
Vue.component('computed-properties-getset', {
data() {
return {
amount: 0,
}
},
computed: {
amountFormatted: {
get() {
return `${this.amount} €`;
},
set(newValue) {
this.amount = newValue;
}
}
},
template: `
<div>
<h2>Computed properties get && set</h2>
<input v-model="amount" />
<p>{{ amountFormatted }}</p>
</div>
`
});
Creamos un v-model
con la referencia de amount
y mostramos en pantalla el amountFormatted
.
Para este ejemplo usaremos más archivos. Vamos a crear dentro de la carpeta components
la carpeta dynamic-components
creando los archivos cmp1.js
, cmp2.js
y cmp3.js
. Dentro de cada archivo habrá lo siguiente, cambiando el nombre del cmp
.
components/dynamic-components/cmp1.js
Vue.component('cmp1', {
template: `
<h4>Componente 1</h4>
`
});
En el index.html
cargamos primero los componentes dinámicos cmpX.js
y después el cargador de componentes load-dynamic-components.js
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
<script src="components/dynamic-components/cmp1.js"></script>
<script src="components/dynamic-components/cmp2.js"></script>
<script src="components/dynamic-components/cmp3.js"></script>
<script src="components/load-dynamic-components.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
<load-dynamic-components></load-dynamic-components>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
En el componente creamos un array
con los nombres de los componentes y decimos cual es el componente actual a mostrar con currentComponent
. En methods creamos un método llamdo changeComponent()
para modificar el componente actual.
En el template visualizamos todos los botones a través de una directiva v-for
y en el evento @click
cambiamos a que botón le hemos dado para actualizar su estado.
/components/load-dynamic-components.js
Vue.component('load-dynamic-components', {
data() {
return {
components: ['cmp1', 'cmp2', 'cmp3'],
currentComponent: 'cmp1',
}
},
methods: {
changeComponent(cmp) {
this.currentComponent = cmp;
}
},
template: `
<div>
<h2>Componentes dinámicos</h2>
<button v-for="cmp in components" :key="cmp" @click="changeComponent(cmp)">
Seleccionar {{ cmp }}
</button>
<component :is="currentComponent" />
</div>
`
});
Para mostrar el componente actual, utilizamos la etiqueta <component>
con la directiva is
(v-bind:is
es lo mismo que :is
) y mostramos que componente es el actual.
Un mixin es una forma de heredar datos para poder reutilizar información.
En el index.html
invocaremos como siempre el archivo javascript
y el componente, en este caso lo hemos llamado <mixins>
. No tenemos que hacer nada más, toda la lógica la lleva el javascript
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
<script src="components/dynamic-components/cmp1.js"></script>
<script src="components/dynamic-components/cmp2.js"></script>
<script src="components/dynamic-components/cmp3.js"></script>
<script src="components/load-dynamic-components.js"></script>
<script src="components/mixins.js"></script>
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
<load-dynamic-components></load-dynamic-components>
<mixins></mixins>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Vamos a crear una variable con todo nuestro mixin
.
/components/mixins.js
let myMixin = {
mounted() {
console.log("MIXIN init");
console.log(this.mixinData);
this.test();
},
data() {
return {
mixinData: `Mixin Data`
}
},
methods: {
test() {
console.log("test from mixin");
}
}
};
Vue.component('mixins', {
mixins: [myMixin],
mounted() {
console.log('Mounted from component with Mixin');
},
data() {
return {
mixinData: `Mixin Data desde el componente`
}
},
template: `
<div>
<h2>Uso de Mixins</h2>
<p>{{ mixinData }}</p>
</div>
`
});
A la hora de crear nuestro componente, deberemos llamar a mixins
en plural en un array, y ahí llamar a nuesta variable con el mixin
. Tenemos que tener cuidado ya que habrán cosas que se ejecutaran antes o después o se pueden reescribir.
Las directivas es mejor que se invoquen al principio. Lo único que vamos a hacer en este ejemplo es darle focus
a un input. Para darle focus creamos una carpeta llamada directives
y dentro de esa carpeta creamos un archivo llamado focus.js
.
En el index.html
le añadimos el archivo javascript
de la directiva.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- VUE DIRECTIVES -->
<script src="directives/focus.js"></script>
<!-- END VUE DIRECTIVES-->
<!-- VUE COMPONENTS -->
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
<script src="components/dynamic-components/cmp1.js"></script>
<script src="components/dynamic-components/cmp2.js"></script>
<script src="components/dynamic-components/cmp3.js"></script>
<script src="components/load-dynamic-components.js"></script>
<script src="components/mixins.js"></script>
<!-- END VUE COMPONENTS-->
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
<load-dynamic-components></load-dynamic-components>
<mixins></mixins>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Creamos la directiva focus
, y le damos focus
al elemento el
.
/directives/focus.js
Vue.directive('focus', {
inserted(el) {
el.focus();
}
});
En el ejemplo vamos a darle focus
al primer input
que habíamos creado (vmodel.js
). Para asignarle la directiva, se la daremos a través de v-nombredirectiva
en este caso v-focus
. El archivo modificado de vmodel.js
quedaría de la siguiente forma.
/components/vmodel.js
Vue.component('vmodel', {
data() {
return {
framework: 'Vuejs2',
}
},
template: `
<div>
<h2>Trabajando con vmodel</h2>
<input v-model="framework" v-focus/>
<p>El framework usado es {{ framework }}</p>
</div>
`
})
Binding son los datos que vamos a pasar a la directiva para poder acceder desde el archivo.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- VUE DIRECTIVES -->
<script src="directives/focus.js"></script>
<script src="directives/change-styles.js"></script>
<!-- END VUE DIRECTIVES-->
<!-- VUE COMPONENTS -->
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
<script src="components/dynamic-components/cmp1.js"></script>
<script src="components/dynamic-components/cmp2.js"></script>
<script src="components/dynamic-components/cmp3.js"></script>
<script src="components/load-dynamic-components.js"></script>
<script src="components/mixins.js"></script>
<!-- END VUE COMPONENTS-->
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message v-change-styles="{backgroundColor: 'red', color: 'white'}"></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
<load-dynamic-components></load-dynamic-components>
<mixins></mixins>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Creando la directiva abajo, usando binding
podemos cambiar los valores de este. En estamos diciendo de introducir un backgroundColor
y un color
. Se lo asignamos al componente que queramos con un v-change-styles
y se le pasamos los valores de esta manera (ejemplo con el componente message
): <message v-change-styles="{backgroundColor: 'red', color: 'white'}"></message>
/directives/change-styles.js
Vue.directive('change-styles', (el, binding) => {
el.style.background = binding.value.backgroundColor;
el.style.color = binding.value.color;
});
Para este ejemplo editaremos el archivo computed-properties-getset.js
donde añadiremos el nombre del filtro y le pasaremos un valor. En el index.html
añadimos el filtro en la carpeta filters
con el archivo currency-filter.js
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- VUE DIRECTIVES -->
<script src="directives/focus.js"></script>
<script src="directives/change-styles.js"></script>
<!-- END VUE DIRECTIVES-->
<!-- VUE FILTERS -->
<script src="filters/currency-filter.js"></script>
<!-- END VUE FILTERS -->
<!-- VUE COMPONENTS -->
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
<script src="components/dynamic-components/cmp1.js"></script>
<script src="components/dynamic-components/cmp2.js"></script>
<script src="components/dynamic-components/cmp3.js"></script>
<script src="components/load-dynamic-components.js"></script>
<script src="components/mixins.js"></script>
<!-- END VUE COMPONENTS-->
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message v-change-styles="{backgroundColor: 'red', color: 'white'}"></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
<load-dynamic-components></load-dynamic-components>
<mixins></mixins>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Creamos el filtro de la siguiente manera, recogiendo el valor y después un currency que será el tipo de moneda.
/filters/currency-filter.js
Vue.filter('currency_filter', (value, currency) => {
return `${value} ${currency}`;
});
Aquí con un pipeline utilizaremos el filtro.
/components/computed-properties-getset.js
Vue.component('computed-properties-getset', {
data() {
return {
amount: 0,
}
},
computed: {
amountFormatted: {
get() {
return `${this.amount}`;
},
set(newValue) {
this.amount = newValue;
}
}
},
template: `
<div>
<h2>Computed properties get && set</h2>
<input v-model="amount" />
<p>{{ amountFormatted | currency_filter('€') }}</p>
</div>
`
});
Un plugin sirve para darle una funcionalidad adicional a VueJS. Para realizar un plugin tenemos que crear un archivo de la siguiente manera:
/plugins/aboutMe.js
const AboutMe = {
install: (Vue, options) => {
const { job } = options;
Vue.prototype.$me = (name, age) => {
return `Mi nombre es ${name} tengo ${age} años y trabajo de ${job}`;
}
//options.job es lo mismo que lo de arriba
}
};
Vue.use(AboutMe, {
job: 'programador e instructor',
})
Creamos una const con los datos y el método install. Le pasamos el primer parámetro que siempre tiene que ser Vue
y después le añadimos unas options
. Destructuramos el objeto con const { job } = options
y le añadimos un prototype
con el nombre $loquesea
para poder llamarlo. En este caso vamos a pedir name
y age
.
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- VUE DIRECTIVES -->
<script src="directives/focus.js"></script>
<script src="directives/change-styles.js"></script>
<!-- END VUE DIRECTIVES-->
<!-- VUE FILTERS -->
<script src="filters/currency-filter.js"></script>
<!-- END VUE FILTERS -->
<!-- VUE COMPONENTS -->
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
<script src="components/dynamic-components/cmp1.js"></script>
<script src="components/dynamic-components/cmp2.js"></script>
<script src="components/dynamic-components/cmp3.js"></script>
<script src="components/load-dynamic-components.js"></script>
<script src="components/mixins.js"></script>
<!-- END VUE COMPONENTS-->
<!-- VUE PLUGIN -->
<script src="plugins/aboutme.js"></script>
<!-- END VUE PLUGIN -->
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message v-change-styles="{backgroundColor: 'red', color: 'white'}"></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
<load-dynamic-components></load-dynamic-components>
<mixins></mixins>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
console.log(this.$me('José Luis', '33'));
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
Una vez más añadimos el script de javascript
y ponemos el componente con varios datos que pasarle al props
. En este caso sería esto: <props name="Jose" surname="García" :age="37"></props>
.
/index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vuejs2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- VUE DIRECTIVES -->
<script src="directives/focus.js"></script>
<script src="directives/change-styles.js"></script>
<!-- END VUE DIRECTIVES-->
<!-- VUE FILTERS -->
<script src="filters/currency-filter.js"></script>
<!-- END VUE FILTERS -->
<!-- VUE COMPONENTS -->
<script src="components/message.js"></script>
<script src="components/computed-properties.js"></script>
<script src="components/methods.js"></script>
<script src="components/vmodel.js"></script>
<script src="components/vmodel-checkboxes.js"></script>
<script src="components/emit.js"></script>
<script src="components/parent-data.js"></script>
<script src="components/child-data.js"></script>
<script src="components/child-methods.js"></script>
<script src="components/login-form.js"></script>
<script src="components/loops.js"></script>
<script src="components/conditionals.js"></script>
<script src="components/slots.js"></script>
<script src="components/watchers.js"></script>
<script src="components/computed-properties-getset.js"></script>
<script src="components/dynamic-components/cmp1.js"></script>
<script src="components/dynamic-components/cmp2.js"></script>
<script src="components/dynamic-components/cmp3.js"></script>
<script src="components/load-dynamic-components.js"></script>
<script src="components/mixins.js"></script>
<script src="components/props.js"></script>
<!-- END VUE COMPONENTS-->
<!-- VUE PLUGIN -->
<script src="plugins/aboutme.js"></script>
<!-- END VUE PLUGIN -->
</head>
<body>
<div id="app" style="margin-bottom: 100px;">
<message v-change-styles="{backgroundColor: 'red', color: 'white'}"></message>
<computed-properties></computed-properties>
<methods></methods>
<vmodel></vmodel>
<vmodel-checkboxes></vmodel-checkboxes>
<emit @show_car_brand="showCarBrandFromEmitCMP"></emit>
<parent-data></parent-data>
<!-- PODEMOS DARLE EL NOMBRE A LA REFERENCIA QUE QUERAMOS-->
<child-data ref="childData"></child-data>
<child-methods ref="childMethod"></child-methods>
<login-form></login-form>
<loops></loops>
<conditionals></conditionals>
<slots>
<p>Contenido del slot para el cuerpo</p>
<template slot="header">
<h3>Header del layout con slot</h3>
</template>
<template slot="footer">
<p>Footer del layout con Slots</p>
</template>
</slots>
<watchers></watchers>
<computed-properties-getset></computed-properties-getset>
<load-dynamic-components></load-dynamic-components>
<mixins></mixins>
<props name="Jose" surname="García" :age="37"></props>
</div>
<script>
new Vue({
el: '#app',
mounted() {
const cmpName = this.$refs.childData.cmpName;
console.log(cmpName);
setTimeout(() => {
this.$refs.childMethod.showCmpName();
},3000);
console.log(this.$me('José Luis', '33'));
},
data() {
return {
appName: 'Iniciando con Vuejs2'
}
},
methods: {
showCarBrandFromEmitCMP(carBrand) {
alert(carBrand);
}
}
});
</script>
</body>
</html>
En el componente, inicializamos una instancia de Vue con el nombre props
, y definimos los valores en el método props
que vamos a pasarle: name
y age
. Además vamos realizar una validación de edad.
/components/.js
Vue.component('props', {
props: {
name: {
type: String,
required: true
},
surname: {
type: String,
required: true
},
age: {
type: Number,
required: true,
validator: value => {
if(value < 18) {
console.warn('No eres mayor de edad...');
return false;
} else {
return true;
}
}
}
},
template: `
<div>
<h2>Props con Vuejs2</h2>
<p>{{ name }} {{ surname }}, Edad {{ age }}</p>
</div>
`
});
Las Props en Vuejs nos permiten pasar datos a un componente al momento de utilizarlo:
<super-componente :nombre="variableNombreSuperComponente" />
En este caso al componente super-componente le estamos pasando un dato de entrada llamado nombre, para utilizarlo en dicho componente haríamos lo siguiente:
<template>
<div>
{{ nombre }}
</div>
</template>
<script>
export default {
props: ['nombre']
}
</script>
El problema está en que si queremos que este dato sea reactivo utilizando v-model tendríamos un error:
<template>
<div>
<input v-model="nombre" />
</div>
</template>
<script>
export default {
props: ['nombre']
}
</script>
[Vue warn]: Avoid mutating a prop directly
Esto significa que no podemos modificar una Prop de forma directa, para solucionar esto realmente existen muchos caminos, pero uno muy común que sirve en la mayoría de los casos es utilizar en lugar de un valor, un objeto:
<super-componente :objetoConNombre="objetoNombreSuperComponente" />
<template>
<div>
<input v-model="objetoConNombre.nombre" />
</div>
</template>
<script>
export default {
props: ['objetoConNombre']
}
</script>
Impresionante. Gracias.
Estoy desarrollando una serie de tutoriales de Vuejs para programadores de jQuery usando el cdn y todo lo de los componentes usados de esta manera me ha quedado muy claro con tu material.
Mil gracias.