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 introduce la siguiente modificación: la tabla mostrada por la tabla HTML se define en un objeto [session] conocido por todos los componentes. Se trata, por tanto, de una forma de compartir información entre componentes. Este concepto se inspira directamente en la sesión web. Utilizamos el método del plugin para 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) {
    // añade una propiedad [$session] a la clase vista
    Object.defineProperty(Vue.prototype, '$session', {
      // cuando se hace referencia a Vue.$session, 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 plugin [pluginSession] se integra en el framework [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] es ahora 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 tabla
      versionTable: 1
    };
  },

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

Comentarios

  • La vista [App] ya no gestiona la tabla mostrada por 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. A continuación, el componente [Table] se regenera 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 solicita 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 vuelve a generar la lista de simulaciones
      this.$session.generateLignes();
      // se solicita 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 fijado por el componente padre, sino un atributo calculado del componente [Table] (líneas 30-32). [lignes] es, por tanto, la matriz [$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: su modificación no se refleja en los componentes que los utilizan. Por este motivo, el componente [Table] solicita a su padre que lo regenere mediante el evento [updateTable] (línea 55). Hemos visto que el componente padre incrementará 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 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].