recherche

Maison  >  Questions et réponses  >  le corps du texte

Améliorez les tables de données avec Vue Router

J'essaie d'ajouter un lien/bouton à une ligne d'un DataTable qui, une fois cliqué, vous amènera à un itinéraire de vue. Bien sûr, je pourrais simplement ajouter un simple <a> 链接,其中包含 href="/item/${id}". Mais cela contourne le routeur et provoque le rechargement de la page entière

J'ai proposé deux solutions, qui reposent toutes deux sur la configuration onclick pour exécuter du code :

  1. Citations en route1中,我将一个名为vueRoute的函数附加到window对象,该函数只是对vue方法route1. Cette fonction peut désormais être appelée de n'importe où

  2. Dans route2, j'ai route2 中,我让 onclick 触发 CustomEvent,并且我设置了一个事件侦听器以由 route2 le déclencheur CustomEvent et j'ai configuré un écouteur d'événement pour le gérer par la méthode vue route2

Je ne suis satisfait d’aucune des deux solutions. Bien qu'ils fonctionnent, ils ont l'air "hacky". Que dois-je faire?

// datatables column definitions
columns: [
  // route1
  {
      data: 'id',
      render: function (dt) {
          return `<a href="#" onclick="(function(){vueRoute('${dt}');})()">route1</a>`;
      },
  },
  // route2
  {
    data: 'id',
    render: function (dt) {
        return `<a href="#" onclick="(function(){document.body.dispatchEvent(
          new CustomEvent('clickedEdit', {detail : ${dt} }));})() ">route2</a>`;
    },
  },
],

// vue methods
methods: {
  route1(id) {
    this.router.push('/item/' + id);
  },

  route2(evt) {
    this.router.push('/item/' + evt.detail);
  },
},

// on mount, set up route1 and route2
mounted() {
  window.vueRoute = this.route1;

  document.body.addEventListener('clickedEdit', this.route2);
},

Un exemple fonctionnel peut être trouvé ici : https://stackblitz.com/edit/datatables-net-vue3-simple-mgdhf1?file=src/components/ListView.vue

EDIT : Ce que j'ai finalement fait, c'est de passer à un composant de table sans tête (TanStack), qui fonctionne mieux dans Vue que DataTables. Mais si vous devez utiliser DataTables, la solution publiée ci-dessous par @Damzaky et @Moritz Ringler fonctionnera très bien

P粉818088880P粉818088880241 Il y a quelques jours374

répondre à tous(2)je répondrai

  • P粉588152636

    P粉5881526362024-03-28 17:27:38

    Je ne dirais pas que c'est la meilleure solution, mais à mon avis, pour autant que je sache, il n'y a pas de véritable "meilleure" solution, puisque le datatable utilise jQuery et que vous utilisez vue ici (incohérence compatible avec le contrôle DOM) . Après une recherche rapide, je n'ai pas trouvé de moyen Affichez un composant vue dans l'attribut render de la table de données.

    Donc mon idée est différente, elle simplifie la fonction de rendu et utilise drawCallback pour ajouter des auditeurs d'événement et utiliser des délégués d'événement pour attacher les auditeurs.

    De Documents :

    data() {
        return {
          ...
          columns: [
            ...
            {
              data: 'id',
              render: function (dt) {
                return `route3`;
              },
            },
          ],
        };
      },
      methods: {
        ...
        drawCallback(settings) {
          const tableElm = document.getElementById(settings.sInstance);
    
          tableElm.addEventListener('click', (e) => {
            const id = e.target.dataset.itemId;
    
            if (id) {
              this.router.push('/item/' + id);
            }
          });
        },
      },
    ...
    

    Donc, j'ajoute simplement data-item-id à chaque lien, puis j'utilise l'événement de clic du parent pour effectuer le push du routeur (délégation d'événement). Je sais que ce n'est pas la meilleure réponse, mais cela pourrait peut-être être une autre option pour vous.

    C'est le bac à sable fourchu si vous êtes intéressé.

    répondre
    0
  • P粉134288794

    P粉1342887942024-03-28 16:25:12

    Vous pouvez définir un gestionnaire @click sur un objet DataTable :

    
    

    L'événement sera un événement de clic régulier, nous avons donc besoin d'un attribut d'ensemble de données d'identification identifiable :

    {
      data: 'id',
      render: function (idValue) {
        return `route3`;
      },
    },

    Le gestionnaire de clics doit simplement s'assurer que l'identifiant peut être récupéré, en s'assurant que le clic provient d'un lien :

    resolveRouteFromClick(e){
      const itemId = e.target.dataset.itemId
      if (!itemId) {
        return
      }
      e.preventDefault()
      this.router.push('/item/' + itemId);
    }

    Voici le Stack Blitz

    mis à jour

    Fait intéressant, tout comme le contexte, le problème n'est même pas la connexion entre Vue et jQuery, mais le fonctionnement des DataTables, en particulier, il n'y a pas d'événements pour le clic sur une cellule ou sur une ligne, et le moteur de rendu ne peut renvoyer que des chaînes HTML.

    Ce n'est pas une surprise, c'est ainsi que fonctionne jQuery, où les données, les vues et les comportements ne sont pas intrinsèquement liés, mais vous pouvez les connecter comme bon vous semble. Nous n'avons donc pas d'événement de clic de cellule à exploiter car dans jQuery vous l'écrivez vous-même ou il n'existe pas.

    Le moyen le plus efficace de définir des gestionnaires dans jQuery est de définir l'événement sur une table à l'aide d'un filtre cible :

    $('.datatable').on('click', 'a[data-item-id]', function(){...})

    Les avantages sont :

    • Un seul événement se produit pour toutes les lignes
    • Pas besoin d'ajouter des événements lors du changement de page ou du nouveau rendu
    • Le code dans la fonction de rendu est réduit au minimum

    La solution Vue ci-dessus fait exactement la même chose, juste sans jQuery.

    Je pense donc que c'est le moyen le plus efficace de le faire fonctionner dans Vue, à la fois en termes de taille de code (maintenabilité) et de performances.

    Notez que puisque DataTable nécessite que jQuery soit accessible globalement, il peut également être utilisé dans votre composant Vue, et vous pouvez placer l'instruction jQuery donnée dans un hook mounted où vous pouvez accéder au Routeur Vue dans le rappel. Ainsi, au lieu de mettre le routeur dans une portée globale pour l'utiliser côté jQuery, vous pouvez utiliser un objet qui existe déjà côté Vue.
    Pourtant, comme il n'est pas nécessaire de mélanger jQuery dans votre code Vue, je l'éviterais et utiliserais la solution Vue uniquement ci-dessus.

    répondre
    0
  • Annulerrépondre