suchen

Heim  >  Fragen und Antworten  >  Hauptteil

Verbessern Sie Datentabellen mit Vue Router

Ich versuche, einer Zeile in einer DataTable einen Link/eine Schaltfläche hinzuzufügen, der Sie beim Klicken zu einer Vue-Route führt. Natürlich könnte ich auch einfach ein schlichtes <a> 链接,其中包含 href="/item/${id}" hinzufügen. Dies umgeht jedoch den Router und führt dazu, dass die gesamte Seite neu geladen wird

Ich habe zwei Lösungen gefunden, die beide auf der Einstellung onclick basieren, um Code auszuführen:

  1. Zitate in route1中,我将一个名为vueRoute的函数附加到window对象,该函数只是对vue方法route1. Diese Funktion kann nun von überall aufgerufen werden

  2. In route2 habe ich route2 中,我让 onclick 触发 CustomEvent,并且我设置了一个事件侦听器以由 route2 den Auslöser CustomEvent und einen Ereignis-Listener eingerichtet, um ihn mit der Vue-Methode route2 zu verarbeiten

Ich bin mit keiner Lösung zufrieden. Obwohl sie funktionieren, sehen sie „hackig“ aus. was soll ich machen?

// 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);
},

Ein funktionierendes Beispiel finden Sie hier: https://stackblitz.com/edit/datatables-net-vue3-simple-mgdhf1?file=src/components/ListView.vue

EDIT: Am Ende habe ich tatsächlich auf eine Headless-Tabellenkomponente (TanStack) umgestellt, die in Vue besser funktioniert als DataTables. Wenn Sie jedoch DataTables verwenden müssen, funktioniert die unten von @Damzaky und @Moritz Ringler veröffentlichte Lösung einwandfrei

P粉818088880P粉818088880241 Tage vor371

Antworte allen(2)Ich werde antworten

  • P粉588152636

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

    我不会说这是最好的解决方案,但在我看来,据我所知,没有真正的“最佳”解决方案,因为数据表使用 jQuery 而你在这里使用 vue (DOM 控件很友好)的不一致)。经过快速搜索,我没有找到办法 在数据表的 render 属性内渲染一个 vue 组件。

    所以我的想法不同,它简化渲染函数,并使用drawCallback添加事件侦听器,并使用事件委托来附加侦听器。

    来自文档

    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);
            }
          });
        },
      },
    ...
    

    因此,我只需将 data-item-id 附加到每个链接,然后使用父级的单击事件来执行路由器推送(事件委托)。我知道这不是最好的答案,但也许这可能是您的另一种选择。

    这个如果您感兴趣的话,这是分叉的沙箱。

    Antwort
    0
  • P粉134288794

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

    您可以在 DataTable 对象上设置 @click 处理程序:

    
    

    该事件将是常规点击事件,因此我们需要一个可识别的 id 数据集属性:

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

    点击处理程序只需确保可以检索 id,确保点击来自链接:

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

    这里是更新后的 堆栈闪电战


    有趣的是,正如背景一样,问题甚至不是 Vue 和 jQuery 之间的连接,而是 DataTables 的工作方式,特别是没有单击单元格或单击行的事件,并且渲染器只能返回 HTML 字符串。

    这并不奇怪,这就是 jQuery 的工作原理,其中数据、视图和行为并不是内在链接的,但您可以按照自己认为合适的方式将它们连接起来。因此,我们没有可以利用的单元格单击事件,因为在 jQuery 中,您自己编写它,否则它就不存在。

    在 jQuery 中设置处理程序的最有效方法是使用目标过滤器在表上设置事件:

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

    优点是:

    • 所有行仅发生一个事件
    • 更改页面或重新渲染时无需添加事件
    • 渲染函数中的代码保持最少

    上面的 Vue 解决方案做了完全相同的事情,只是没有 jQuery。

    所以我认为这是使其在 Vue 中工作的最有效方法,无论是在代码量(可维护性)还是性能方面。

    请注意,由于 DataTable 要求 jQuery 可以全局访问,因此它也可以在您的 Vue 组件中使用,并且您可以将给定的 jQuery 语句放入 mounted 挂钩中,您可以在其中访问 Vue 路由器在回调中。因此,您不必将路由器置于全局范围内以便在 jQuery 端使用它,而是可以使用 Vue 端已有的对象。
    尽管如此,由于没有必要将 jQuery 混合到您的 Vue 代码中,所以我会避免它并使用上面的仅 Vue 解决方案。

    Antwort
    0
  • StornierenAntwort