6. proyecto [vuejs-04]: directivas [v-model, v-bind], atributos calculados, formulario de entrada
La estructura del proyecto [vuejs-04] es la siguiente:

6.1. El script principal [main.js]
Es el mismo que en el ejemplo anterior.
6.2. El componente principal [App]
El código de [App.vue] es el siguiente:
<template>
<b-container>
<b-card>
<!-- mensaje de presentación -->
<b-row>
<b-col cols="8">
<b-alert show variant="success" align="center">
<h4>[vuejs-04] : directives [v-model, v-bind], attributs calculés, formulaire de saisie</h4>
</b-alert>
</b-col>
</b-row>
<Form />
</b-card>
</b-container>
</template>
<script>
import Form from "./components/Form.vue";
export default {
name: "app",
components: {
Form
}
};
</script>
El componente [App.vue] utiliza el nuevo componente [Form] (líneas 12, 19, 24).
6.3. El componente [Form]
El código del componente [Form] es el siguiente:
<template>
<div>
<!-- formulario -->
<b-form>
<!-- elementos del formulario -->
<b-row>
<b-col cols="4">
<b-card bg-variant="light">
<b-form-group label="Nombre d'enfants à charge" label-for="enfants">
<b-input type="text"
id="enfants"
placeholder="Indiquez votre nombre d'enfants"
v-model="enfants"
v-bind:state="enfantsValide" />
<b-form-invalid-feedback :state="enfantsValide">Vous devez saisir un nombre positif ou nul</b-form-invalid-feedback>
</b-form-group>
<!-- botón -->
<b-button variant="primary" :disabled="formInvalide" @click="doSomething">Valider</b-button>
</b-card>
</b-col>
</b-row>
</b-form>
<b-row class="mt-3">
<b-col cols="4">
<b-alert show variant="warning" align="center">
<h4>enfants= {{enfants}}</h4>
</b-alert>
</b-col>
</b-row>
</div>
</template>
<!-- script -->
<script>
export default {
// nombre
name: "Form",
// atributos estáticos del componente
data() {
return {
// número de hijos
enfants: ""
};
},
// atributos calculados
computed: {
// atributo [formInvalide]
formInvalide() {
return !this.enfantsValide;
},
// atributo [enfantsInvalide]
enfantsValide() {
return Boolean(this.enfants.match(/^\s*\d+\s*$/));
}
},
// métodos
methods: {
doSomething() {
// el número de hijos se conoce cuando se realiza la validación
alert("Nombre d'enfants : " + this.enfants);
}
}
};
</script>
Representación visual


Comentarios
- líneas 4-32: la etiqueta <b-form> introduce un formulario Bootstrap;
- línea 6: la etiqueta <b-row> introduce una fila en el formulario;
- línea 7: la etiqueta <b-col cols=’4’> introduce una columna que ocupa 4 columnas de Bootstrap;
- línea 8: la etiqueta <b-card> [6] introduce una tarjeta Bootstrap, un área enmarcada por un borde;
- línea 9: la etiqueta <b-form-group> introduce un grupo de elementos del formulario vinculados entre sí. Aquí, un texto (atributo [label]) [1] está vinculado a un campo de entrada (atributo [label-for]). El valor de [label-for] es el valor del campo [id], línea 12, del campo de entrada;
- líneas 10-14: la etiqueta <b-input> [2] introduce un campo de entrada:
- línea 10: [type=’text’] indica que se puede escribir texto en el campo de entrada. Se podría haber escrito [type=’number’] con restricciones [min=’val1’ max=’val2’ step=’val3’], ya que se espera un número de elementos secundarios. Se ha puesto [type=’text’] para mostrar cómo verificar la validez de una entrada;
- línea 12: el atributo [placeholder] [3] establece el mensaje que se muestra en el campo de entrada mientras el usuario no haya introducido nada;
- línea 13: la directiva [v-model] asocia, de forma bidireccional, el valor introducido con el atributo [enfants], línea 42, del componente:
- cuando cambia el valor introducido, también cambia el valor del atributo [enfants];
- cuando cambia el valor del atributo [enfants], entonces el valor introducido también cambia, es decir, cambia el contenido de [2];
- lo importante es comprender que, gracias al mecanismo anterior, cuando el usuario hace clic en el botón [Valider] [5], el atributo [enfants] de la línea 42 toma como valor el valor introducido en [2];
- línea 14: la directiva [v-bind] establece un enlace entre, por un lado, un atributo de la etiqueta <b-input>, en este caso el atributo [state], y un atributo del componente, en este caso [enfantsValide], línea 53. El atributo [enfantsValide] es especial en el sentido de que es una función que devuelve el valor del atributo. A este tipo de atributo se le denomina «atributo calculado». Los atributos calculados se encuentran en la propiedad [computed], línea 47, del componente. Los atributos calculados se utilizan de la misma manera que los atributos estáticos de la función [data]: en la línea 14 no se escribe [v-bind:state=’enfantsValide()’], sino [v-bind:state=’enfantsValide’], sin paréntesis. Además, al leer [template], no se puede distinguir un atributo calculado de un atributo estático. Para ello, hay que consultar el código del script del componente;
- línea 14: el atributo [state] determinará el estado válido/inválido del valor introducido: si [enfantsValide] devuelve el valor [true], el valor introducido se considera válido; en caso contrario, se considera inválido. La captura de pantalla anterior muestra el componente [b-input] cuando la función [enfantsValide] devuelve el valor [false];
- línea 15: la etiqueta <b-form-invalid-feedback> [4] permite mostrar un mensaje cuando la entrada en [2] no es válida. Su atributo [:state=’enfantsValide’] es idéntico al atributo [v-bind:state=’enfantsValide’] de la línea 14. Se puede omitir la directiva [v-bind], pero hay que mantener el signo [:]. Por lo tanto, el mensaje de error aparece cuando el atributo [enfantsValide] es igual a [false];
- línea 16: fin del grupo de elementos <b-group>;
- línea 18: el botón [5] que permitirá validar la entrada:
- será de color azul [variant=’primary’];
- [:disabled="formInvalide"]: el atributo [disabled] permite validar o invalidar el botón. Este atributo está vinculado (v-bind) al atributo calculado [formInvalide] de la línea 49;
- [@click="doSomething"]: cuando el usuario haga clic en el botón, se ejecutará el método [doSomething], línea 59;
- líneas 19-22: cierre de las diferentes etiquetas abiertas;
- líneas 23-29: una nueva línea en [template]. [class=’mt-3’] significa [margin (m) top (t) égale à 3 spacers]. [spacer] es una medida de espaciado de Bootstrap. Esta clase genera el espaciado [8] en la captura de pantalla anterior. Sin esta clase, el área [7] queda pegada al área [1-6];
- línea 24: una columna que ocupa 4 columnas de Bootstrap;
- líneas 25-27: una alerta [warning] que muestra el valor del atributo estático [enfants] (línea 42). Dado que este atributo tiene un enlace bidireccional con el campo de entrada, en cuanto el usuario lo modifica, el valor mostrado en la alerta también cambia;
- líneas 34-65: el código jS del componente;
- línea 42: el único atributo estático del componente;
- líneas 47-56: los atributos calculados del componente;
- líneas 53-55: la entrada se considera válida si es un número entero positivo, eventualmente precedido o seguido de «espacios»;
- líneas 49-51: el formulario se considera válido si la entrada del número de hijos es válida. En general, un formulario tiene varias entradas y se considera válido si todas ellas son válidas;
- líneas 58-63: los métodos del componente que reaccionan a sus eventos. Aquí solo hay un evento: el [click] en el botón. Nos limitamos a mostrar el valor introducido para demostrar que tenemos acceso a él;
6.4. Ejecución del proyecto
Modificamos el archivo [package.json] y ejecutamos el proyecto:
