首頁  >  問答  >  主體

使用 Vue Router 增強資料表

我正在嘗試在 DataTable 中的行中新增連結/按鈕,點擊後會將您帶到 vue 路線。當然,我可以簡單地添加一個普通的 <a> 鏈接,其中包含 href="/item/${id}"。但這會繞過路由器並導致整個頁面重新載入

我想出了兩個解決方案,這兩個解決方案都依賴設定 onclick 來執行一些程式碼:

  1. route1中,我將一個名為vueRoute的函數附加到window對象,該函數只是對vue方法 route1的引用。現在可以從任何地方呼叫此函數

  2. route2 中,我讓onclick 觸發CustomEvent,並且我設定了一個事件偵聽器以由route2 vue 方法處理它

我對這兩種解決方案都不滿意。儘管它們有效,但它們看起來很「hacky」。我該做什麼?

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

可以在此處找到工作範例:https://stackblitz.com/edit/datatables-net-vue3-simple-mgdhf1?file=src/components/ListView.vue

#編輯:我實際上最終做的是切換到無頭表元件(TanStack),它在 Vue 中運行得比 DataTables 更好。但如果您需要使用 DataTables,@Damzaky 和 ​​@Moritz Ringler 下面發布的解決方案可以正常工作

P粉818088880P粉818088880205 天前340

全部回覆(2)我來回復

  • 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 附加到每個鏈接,然後使用父級的單擊事件來執行路由器推送(事件委託)。我知道這不是最好的答案,但也許這可能是您的另一種選擇。

    這個如果您有興趣的話,這是分叉的沙箱。

    回覆
    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 解決方案。

    回覆
    0
  • 取消回覆