使用 Vue Router 增强数据表
P粉818088880
P粉818088880 2024-03-27 22:03:12
0
2
376

我正在尝试向 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粉818088880
P粉818088880

全部回复(2)
P粉588152636

我不会说这是最好的解决方案,但在我看来,据我所知,没有真正的“最佳”解决方案,因为数据表使用 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 附加到每个链接,然后使用父级的单击事件来执行路由器推送(事件委托)。我知道这不是最好的答案,但也许这可能是您的另一种选择。

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

P粉134288794

您可以在 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 解决方案。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板