Conjunto de herramientas, librerías y/o técnicas que nos permiten resolver un problema de una manera más elegante, sencilla y que nos permitirá resolver problemas nuevos similares de la misma manera.
Muchos frameworks nos proporcionan una estructura del proyecto ha seguir y siempre la misma, muchos framworks nos facilitan resolver problemas comunes de manera sencilla (digamos que, como jquery lo hacía con la manipulación del dom) etc etc
Tanto, que ya no se le llaman webs, y nace el concepto de
WEBAPPS
FACEBOOK, WHATSAPP WEB, SPOTIFY, APLICACIONES MÓVILES HÍBRIDAS, APLICACIONES DE ESCRITORIO CON ELECTRON
index.html
<div>
</div>
Ordenador usuario
Servidor facebook
== DAME EL index.HTML =>
<= Toma el index.html ==
== El usuario navega a categories.html =>
Se refresca la pantalla
== NAVEGO a categorias.html =>
<= Toma el categorias.html ==
Se refresca la pantalla
Dame todos los ficheros
Toma los scripts y los css
Dame todos los ficheros
Toma los scripts y los css
Ordenador usuario
Servidor facebook
== DAME EL index.HTML =>
<= Toma el index.html ==
== El usuario navega a categories.html =>
Se refresca la pantalla
== NAVEGO a categorias.html =>
<= Toma el categorias.html ==
Se dibuja dentro del contenedor
Dame todos los ficheros
Toma los scripts y los css
Ordenador usuario
Servidor facebook
== DAME EL index.HTML =>
<= Toma el index.html ==
== El usuario navega a categories.html =>
Se refresca la pantalla
NAVEGO a categorias.html
Me autosirvo el template
Me renderizo una cosa nueva
Dame todos los ficheros
Toma los scripts y los css
REACT
EMBER
BACKBONES
ANGULAR
VUEJS
ETC ETC ...
Anteriormente, se usaba la estructura de webpack, ahora se parece más y concuerda con la típica estructura de Vite.
¿Te recuerda al mkweb?
Pues mediante los comandos del package.json
npm run dev / npm run build
Vamos a trabajar con la "Options"
Este es el APP.vue
<template>
<h1> {{ name }} </h1>
</template>
<script>
export default {
name : 'todo-list',
data () {
return {
name : 'Pruebas'
}
}
}
</script>
<style scoped>
</style>
<script>
export default {
name : 'todo-list',
data () {
return {
name : 'Pruebas'
}
}
}
</script>
<div class="usuario">
<h1 id="nombre"></h1>
<input type="number" id="edad"/>
</div>
function dibujarUsuario (usuario) {
$('#nombre').text(usuario.nombre);
$('#edad').val(usuario.edad);
}
function recogerValores(){
var nombre = $('#nombre').text();
var edad = $('#edad').val();
}
<template>
<div>
<h1> My name is {{ user.name }} </h1>
<h2> I am {{ user.age }} years old </h2>
</div>
</template>
<script>
export default {
name : 'user-element',
data() {
return {
user : {
name : 'Jhon Doe',
age : 20
}
}
}
}
</script>
<template>
<div>
<h1> My name is {{ name }} </h1>
<h2 v-once> I am {{ age }} years old </h2>
<textarea v-html="description"></textarea>
</div>
</template>
Relación modelo => vista
<template>
<div>
<h1> My name is {{ name }} </h1>
<h2> I am {{ age }} years old </h2>
<textarea v-html="description"></textarea>
<input v-model="age" type="number">
</div>
</template>
Relación vista => modelo
<template>
<div class="users">
<div>
<h1> My name is {{ users[0].name }} </h1>
<h2 v-once> I am {{ users[0].age }} years old </h2>
<textarea v-html="users[0].description"></textarea>
<input v-model="users[0].age" type="number">
</div>
<div>
<h1> My name is {{ users[1].name }} </h1>
<h2 v-once> I am {{ users[1].age }} years old </h2>
<textarea v-html="users[1].description"></textarea>
<input v-model="users[1].age" type="number">
</div>
</div>
</template>
¡ Dibujamos todos los elementos del array de uno en uno !
... ... es coña xD ZERO LINES !
<template>
<div class="users">
<div v-for="user in users">
<h1> My name is {{ user.name }} </h1>
<h2> I am {{ user.age }} years old </h2>
<textarea v-html="user.description"></textarea>
<input v-model="user.age" type="number">
</div>
</div>
</template>
<template>
<div class="users">
<div v-for="user in users">
<h1> My name is {{ user.name }} </h1>
<h2> I am {{ user.age }} years old </h2>
<textarea v-html="user.description"></textarea>
<input v-model="user.age" type="number">
</div>
</div>
</template>
export default {
name : 'user-element',
data () {
return {
users: [{} , {}]
}
}
}
<!-- Este sería sin pasar parámetros, simplemente asociamos -->
<button v-on:click="addUser" > Añadir </button>
<!-- Este sería si quieres pasar parámetros -->
<button v-on:click="addUser('paco', 20)" > Añadir </button>
export default {
data () {
return { ... }
},
methods : {
addUser (parametros) {
...
}
}
}
export default {
name: "user-element",
data() {
return {
user: {
name: "",
age: 0,
description: "",
email: ""
}
};
},
methods: {
add() {
console.log('Datos usuario:');
console.log(this.user);
}
},
}
export default {
name: "user-element",
data() {
return {
user: {
name: "",
age: 0,
description: "",
email: ""
}
};
},
methods: {
add() {
console.log('Datos usuario:');
console.log(this.user);
}
},
}
methods: {
add() {
if ( this.validateUser(this.user) ){
console.log('Validado');
}
},
validateUser (user) {
return true;
}
},
methods: {
add() {
if ( validateUser(this.user) ){
console.log('Validado');
}
},
validateUser (user) {
return true;
}
},
methods: {
add : () => {
if ( this.validateUser(this.user) ){
console.log('Validado');
}
},
validateUser (user) {
return true;
}
},
<button v-on:click="addUser" > Añadir </button>
<input
placeholder="Introduce el nombre"
v-model:"user.name"
v-on:blur="validateName"
v-on:keyup.enter="validateName"
v-on:focus="showTip"
/>
<input
placeholder="Introduce el nombre"
v-model:"user.name"
v-on:blur="validateName"
v-on:keyup.mouseenter.once="showTip"
/>
<button v-on:click.prevent="addUser" > Añadir </button>
<img
v-bind:src="image.link"
v-bind:alt="image.alt"
v-bind:title="image.title"
/>
<a v-bind:href="nuevaRuta"> pincha aquí </a>
<img
v-bind:class="image.classes"
/>
<div
class="user"
v-bind:class="{ 'isActive' : user.isActive }"
></div>
Se aplicará la clase 'isActive' si la condicion de la derecha se cumple, en esa caso, si la variable user.isActive da true
Le puedes pasar un array de clases [ 'clase1, 'clase2']
<div
class="user"
v-bind:style="{ propiedad : valor , fontSize : user.fuente, color : user.color }"
></div>
Hacemos proyecto todo-list en directo de cero todos a la vez
v-if v-else v-else-if
<div class="user">
<h1> Mi nombre es {{user.name}}</h1>
<p v-if="mostrarEdad"> Tengo {{user.age}} años</p>
<button @click="mostrarEdad = !mostrarEdad">Mostrar edad</button>
</div>
<script>
export default {
data () {
return {
mostrarEdad : false
}
}
}
</script>
v-if v-else v-else-if
<div class="user">
<h1> Mi nombre es {{user.name}}</h1>
<p v-if="mostrarEdad"> Tengo {{user.age}} años</p>
<p v-if="!mostrarEdad"> No te puedo decir mi edad</p>
<button
@click="mostrarEdad = !mostrarEdad"
v-if="!mostrarEdad"
>Mostrar edad</button>
<button
@click="mostrarEdad = !mostrarEdad"
v-else
>Ocultar edad</button>
</div>
Os toca a ustedes ahora
Hacer el tutorial que tiene vuejs hasta el paso 7 de manera individual
<ul class="lista-compra">
<li v-for="item in items"> {{item.name}} x {{ item.price }}€</li>
</ul>
<p> Precio total : {{ totalPrice }} </p>
export default {
name: 'App',
data () : ...,
computed : {
totalPrice () {
let result = 0;
this.items.forEach( item => result += item.price)
return result;
}
}
};
<div class="users">
<div
class="user"
v-for="user in usersFiltered">
</div>
</div>
computed : {
usersFiltered () {
let results = [];
results = /* only user.name.includes() */;
if (this.onlyWatchNotContacted){
results = /* only !user.contacted */
}
/* More filters */
return results;
}
}
<input v-model="user.name">
<small v-if="errors.nameInvalid">
El nombre de usuario introducido no es válido
</small>
watch : {
'user.name' () {
let isValid = /* do things */;
this.errors.invalidName = isValid;
}
}
<input type="text" placeholder="nombre"
v-model="nuevo.name"
@keyup.enter="add">
watch : {
'nuevo.name': function () {
console.log(this.nuevo.name);
if (this.nuevo.name.toLowerCase() === 'pera'){
alert('está prohibido comprar peras');
this.nuevo.name = '';
}
}
},
<input type="text" placeholder="Nuevo todo"
v-model="newTodo.title">
<button :disabled="newTodoIsInvalid"
@click="add"> Añadir </button>
watch : {
'newTodo.title': function () {
if ( /* invalid */ )
this.newTodoIsInvalid = true;
else
this.newTodoIsInvalid = false;
}
},
<input type="text" placeholder="Nuevo todo"
v-model="newTodo.title">
<button :disabled="newTodoIsInvalid"
@click="add"> Añadir </button>
computed : {
newTodoIsInvalid: function () {
if ( /* invalid */ )
return true;
else
return false;
}
},
Mejor usar un computed para estas cosas
Pues lo mismo pero con VueJS :P
¿ Recuerdan este ejercicio ?
- Le ponemos validaciones a medida que el usuario va haciendo blur
- Le añadimos feedback visual si el formulario ya está correcto o si hay algo mal (deshabilitamos botón)
- Añadimos un buscador por texto y/o buscador por cada campo
Cosas que puntuan
Importamos Axios y recogemos los usuarios la API y los mandamos a la api
https://jsonplaceholder.typicode.com/users
index.html
<router-view>
</router-view>
Creamos un proyecto con router.
Vamos a realizar un proyecto con una vista en modo lista donde mostramos la previsualización de unos elementos, en este caso de los usuarios y donde cada cajita tiene un botón de "ver más".
Al clickar en ver más navegamos a /details/:id y en esta vista vamos a renderizar una vista nueva donde vamos a buscar a la api ese usuario a la API y donde mostramos todos sus campos y un botón de "volver atrás"