Skip to content

15. proyecto [vuejs-13]: actualización de un componente, uso de una sesión

El proyecto [vuejs-13] retoma el proyecto [vuejs-12] e incorpora la siguiente modificación: la tabla que muestra la tabla HTML se define en un objeto [session] conocido por todos los componentes. Por lo tanto, es una forma de compartir información entre componentes. Este concepto se inspira directamente en la sesión web. Utilizamos el método del complemento para hacer que este objeto compartido esté disponible en un atributo [Vue.$session].

La estructura del proyecto es la siguiente:

Image

15.1. El objeto [session]

El objeto [session], compartido por todos los componentes, se define en el script [./session.js]:


const session = {
  // lista de simulaciones
  get lignes() {
    return this._lignes;
  },
  // generación de la lista de simulaciones
  generateLignes() {
    this._lignes =
      [
        { id: 3, marié: "oui", enfants: 2, salaire: 35000, impôt: 1200 },
        { id: 5, marié: "non", enfants: 2, salaire: 35000, impôt: 1900 },
        { id: 7, marié: "non", enfants: 0, salaire: 30000, impôt: 2000 }
      ]
  },
  // eliminación de la línea n.º índice
  deleteLigne(index) {
    this._lignes.splice(index, 1);
  }
}
// exportación del objeto [session]
export default session;

15.2. El complemento [./plugins/pluginSession]

El script [pluginSession] es el siguiente:


export default {
  install(Vue, session) {
    // agrega una propiedad [$session] a la clase vista
    Object.defineProperty(Vue.prototype, '$session', {
      // cuando se hace referencia a Vue.$session se hace referencia, se devuelve el segundo parámetro [session] del método [install]
      get: () => session,
    })
  }
}
  • línea 4: el objeto compartido [session] estará disponible en la propiedad [$session] de todos los componentes;

15.3. El script principal [main.js]

El script principal [main.js] es el siguiente:


// importaciones
import Vue from 'vue'
import App from './App.vue'

// plugins
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue);

// bootstrap
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

// sesión
import session from './session';
import pluginSession from './plugins/pluginSession'
Vue.use(pluginSession, session)

// configuración
Vue.config.productionTip = false

// instanciación del proyecto [App]
new Vue({
  name: "app",
  render: h => h(App),
}).$mount('#app')
  • líneas 14-16: el complemento [pluginSession] se integra en el marco [Vue.js];
  • después de la línea 16, el atributo [$session] está disponible para todos los componentes;

15.4. La vista principal [App]

La vista [App] ahora es la siguiente:


<template>
  <div class="container">
    <b-card>
      <!-- mensaje -->
      <b-alert show variant="success" align="center">
        <h4>[vuejs-13] : mise à jour d'un composant, partage des données avec une session</h4>
      </b-alert>
      <!-- tabla HTML -->
      <Table @updateTable="updateTable" :key="versionTable"/>
    </b-card>
  </div>
</template>

<script>
import Table from "./components/Table";
export default {
  // nombre
  name: "app",
  // componentes
  components: {
    Table
  },
  // estado interno
  data() {
    return {
      // versión de la tabla
      versionTable: 1
    };
  },

  // métodos
  methods: {
    updateTable() {
      // eslint-desactivar-línea-siguiente
      console.log("App updateTable");
      // incremento de la versión de la tabla
      this.versionTable++;
    }
  }
};
</script>

Comentarios

  • La vista [App] ya no gestiona la tabla que muestra el componente [Table] de la línea 9;
  • línea 9: el componente [Table] emite el evento [updateTable], que solicita que se regenere el componente [Table]. Una forma de hacerlo es utilizar el atributo [:key]. A este atributo se le asigna un valor modificable. Cada vez que se modifica, se regenera el componente [Table];
  • línea 9: el valor del atributo [:key] es el atributo [versionTable] de la línea 27. El método [updateTable] (líneas 33-38) se encarga de regenerar el componente [Table] de la línea 9. Para ello, el método incrementa el valor del atributo [:key] del componente [Table], línea 37. El componente [Table] se regenera entonces automáticamente;

15.5. El componente [Table]

El componente [Table] evoluciona de la siguiente manera:


<template>
  <div>
    <!-- lista vacía -->
    <template v-if="lignes.length==0">
      <b-alert show variant="warning">
        <h4>Votre liste de simulations est vide</h4>
      </b-alert>
      <!-- botón de recarga-->
      <b-button variant="primary" @click="rechargerListe">Recharger la liste</b-button>
    </template>
    <!-- lista no vacía-->
    <template v-if="lignes.length!=0">
      <b-alert show variant="primary" v-if="lignes.length==0">
        <h4>Liste de vos simulations</h4>
      </b-alert>
      <!-- tabla de simulaciones -->
      <b-table striped hover responsive :items="lignes" :fields="fields">
        <template v-slot:cell(action)="row">
          <b-button variant="link" @click="supprimerLigne(row.index)">Supprimer</b-button>
        </template>
      </b-table>
    </template>
  </div>
</template>

<script>
export default {
  // estado calculado
  computed: {
    lignes() {
      return this.$session.lignes;
    }
  },
  // estado interno
  data() {
    return {
      fields: [
        { label: "#", key: "id" },
        { label: "Marié", key: "marié" },
        { label: "Nombre d'enfants", key: "enfants" },
        { label: "Salaire", key: "salaire" },
        { label: "Impôt", key: "impôt" },
        { label: "", key: "action" }
      ]
    };
  },
  // métodos
  methods: {
    supprimerLigne(index) {
      // eslint-disable-next-line
      console.log("Table supprimerLigne", index);
      // se elimina la línea
      this.$session.deleteLigne(index);
      // se le pide al componente padre que actualice la vista
      this.$emit("updateTable");
    },
    // recarga de la lista mostrada
    rechargerListe() {
      // eslint-disable-next-line
      console.log("Table rechargerListe");
      // se regenera la lista de simulaciones
      this.$session.generateLignes();
      // se le pide al componente padre que actualice la vista
      this.$emit("updateTable");
    }
  }
};
</script>

Comentarios:

  • el atributo [lignes] (líneas 4, 12, 17) ya no es un parámetro establecido por el componente padre, sino un atributo calculado del componente [Table] (líneas 30-32). [lignes] es, por lo tanto, la tabla [$session.lignes] (línea 31);
  • líneas 49-56: el método [supprimerLigne] elimina una línea de la tabla [$session.lignes]. Por defecto, esta eliminación no modifica la visualización de la tabla HTML. De hecho, los elementos de [$session] no son reactivos: sus modificaciones no se reflejan en los componentes que los utilizan. Por esta razón, el componente [Table] solicita a su componente padre que lo regenere mediante el evento [updateTable] (línea 55). Ya vimos que el componente padre incrementaría entonces el atributo [:key] del componente [Table] para forzar su regeneración;
  • líneas 58-65: el método [rechargerListe] solicita al objeto [$session] que regenere la tabla [$session.lignes]. Por la misma razón que antes, esta modificación de [$session.liste] no cambia, por defecto, la visualización de la tabla HTML. Por este motivo, el componente [Table] solicita a su componente padre que lo regenere mediante el evento [updateTable] (línea 64).

15.6. Ejecución del proyecto

Image

Se obtienen los mismos resultados que en el proyecto [vuejs-12].