javascript 正确实现 Vue.js + DataTables

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32755853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 15:43:05  来源:igfitidea点击:

Implementing Vue.js + DataTables properly

javascriptjquerydatatablesvue.js

提问by Chris Landeza

Im trying to implement Vue.js + jQuery's DataTables but there's a weird things happening.

我正在尝试实现 Vue.js + jQuery 的 DataTables,但发生了一件奇怪的事情。

Check this fiddle on firefox (not working on chrome): http://jsfiddle.net/chrislandeza/xgv8c01y/

在 Firefox 上检查这个小提琴(不适用于 chrome)http: //jsfiddle.net/chrislandeza/xgv8c01y/

when I change the state of DataTable (e.g. sort, search, etc.):

当我更改 DataTable 的状态时(例如排序、搜索等):

  • Newly added data on the list disappears
  • The DOM is not reading the directives or the vue properties
  • 列表中新增数据消失
  • DOM 没有读取指令或 vue 属性

I'm pretty sure anyone who tried to mix vue.js+datatables experienced this problem. what did you do to solve this?

我很确定任何试图混合 vue.js+datatables 的人都遇到过这个问题。你做了什么来解决这个问题?

or is there a pure Vue.js script/plugin that has the same (or close) functionality like jquery's DataTable? (pagination, searching, sorting, number of entries to show, etc.).

或者是否有纯 Vue.js 脚本/插件具有与 jquery 的 DataTable 相同(或接近)的功能?(分页、搜索、排序、要显示的条目数等)。

here's the code from the fiddle above:

这是上面小提琴中的代码:

HTML:

HTML:

<div class='container-fluid' id="app">
        <div class='row'>
            <div class='col-md-9'>
                <table class="table table-bordered" id="app-datatable">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Age</th>
                            <th></th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-repeat="user: users">
                            <td>{{ user.name }}</td>
                            <td>{{ user.age }}</td>
                            <td>
                                <button type="button" v-on="click: foo(user)">Action</button>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class='col-md-3'>
                <div class="form-group">
                    <label>Name</label>
                    <input type="text"
                           class="form-control"
                           v-model="newUser.name"
                           >
                </div>

                <div class="form-group">
                    <label>Age</label>
                    <input type="name"
                           class="form-control"
                           v-model="newUser.age"
                           >
                </div>
                <button type="submit" class="btn btn-primary" v-on="click: addUser()">Add</button>
            </div>
        </div>
    </div>

JavaScript:

JavaScript:

$(document).ready(function () {
    var dT = $('#app-datatable').DataTable();
});

var vm = new Vue({
    el: '#app',
    data: {
        newUser: {},
        users: [
            {name: 'Chris', age: 1},
            {name: 'John', age: 2}
        ]
    },
    methods:{
        addUser: function(){
           this.users.push(this.newUser);
           this.newUser = {};
        },
        foo: function(user){
            console.log(user.name);
        }
    }
});

any suggestions are greatly appreciated.

非常感谢任何建议。

回答by Nik

To get the DataTables plugin integrated correctly with Vue, there are a few things to keep in mind:

要使 DataTables 插件与 Vue 正确集成,需要记住以下几点:

  1. Per your example, you can use var dT = $('#app-datatable').DataTable();to initialize the DataTables if you already have the data ready and rendered to the DOM. If you don't have the DOM <table></table>fully rendered (perhaps due to data populated via a delayed ajax call), you can't initialize the DataTables until the data is ready. As an example, if you have a fetchDatamethod in your component, you can initialize the DataTable once the promise has been fulfilled.

  2. To update the table once initialized, perhaps due to a change in the underlying table data, the best (perhaps the only way), is to first destroy the table, before the new data is received and written to the DOM by Vue:

    var dT = $('#app-datatable').DataTable();
    dT.destroy();
    

    Then, once the data (in your case, the users array) has been updated, re-initialize the DataTable as so:

    this.$nextTick(function() {
       $('#app-datatable').DataTable({
          // DataTable options here...
       });
    })
    

    The $nextTick is necessary to ensure Vue has flushed the new data to the DOM, before re-initializing. If the DOM is updated after the DataTable plugin has been initialized, you'll see the table data, but the usual sorting, paging, etc. won't work.

  3. Another important point, is to have a row id in your dataset, and set the key in the <tr></tr>:

    <tr v-repeat="user: users" track-by="id">

    Without the track-by, Vue will complain when flushing new data to the DOM after DataTables has been initializing, likely due to not finding DOM elements hi-Hymaned by DataTables.

  1. 根据您的示例,var dT = $('#app-datatable').DataTable();如果您已经准备好数据并呈现到 DOM ,则可以使用它来初始化 DataTables。如果您没有<table></table>完全呈现DOM (可能是由于通过延迟的 ajax 调用填充数据),则在数据准备好之前无法初始化 DataTables。例如,如果您fetchData的组件中有一个方法,您可以在承诺完成后初始化 DataTable。

  2. 更新表一旦初始化,可能是由于底层表数据的变化,最好的(也许是唯一的方法)是先销毁表,然后 Vue 接收新数据并将其写入 DOM:

    var dT = $('#app-datatable').DataTable();
    dT.destroy();
    

    然后,一旦数据(在您的情况下,用户数组)已更新,重新初始化 DataTable 如下:

    this.$nextTick(function() {
       $('#app-datatable').DataTable({
          // DataTable options here...
       });
    })
    

    $nextTick 是确保 Vue 在重新初始化之前将新数据刷新到 DOM 所必需的。如果在 DataTable 插件初始化后更新 DOM,您将看到表格数据,但通常的排序、分页等将不起作用。

  3. 另一个重要的一点是,在您的数据集中有一个行 ID,并在以下位置设置键<tr></tr>

    <tr v-repeat="user: users" track-by="id">

    如果没有track-by,Vue 会在 DataTables 初始化后将新数据刷新到 DOM 时抱怨,这可能是因为没有找到被 DataTables 劫持的 DOM 元素。

回答by ouyangxuanyun

maybe you can use lifecycle hooks, infact these weird things are caused by competition of manipulating the DOM. in your vue instance, add a created() hook then initialize the DataTable, just like the following:

也许你可以使用生命周期钩子,事实上这些奇怪的事情是由操纵 DOM 的竞争引起的。在你的 vue 实例中,添加一个 created() 钩子,然后初始化 DataTable,就像下面这样:

var vm = new Vue({
el: '#app',
data: {
    newUser: {},
    users: [
        {name: 'Chris', age: 1},
        {name: 'John', age: 2}
    ]
},
methods:{
    addUser: function(){
       this.users.push(this.newUser);
       this.newUser = {};
    },
    foo: function(user){
        console.log(user.name);
    }
},
created(){
      this.$nextTick(function() {
        $('#app-datatable').DataTable();
      })
    }

});

});

回答by Jonathan Ross

I have externally supplied table data (not an Ajax call from DataTable) and destroying / re-creating the table using only these lifecycle hooks is working for me:

我已经从外部提供了表数据(不是来自 的 Ajax 调用DataTable)并且仅使用这些生命周期挂钩来销毁/重新创建表对我有用:

beforeUpdate: function() {
    if (this.dataTable) {
        this.dataTable.destroy()
    }
},
updated: function() {
    this.dataTable = $(this.$el).DataTable()
}

From https://alligator.io/vuejs/component-lifecycle/

来自https://alligator.io/vuejs/component-lifecycle/

"The beforeUpdate hook runs after data changes on your component and the update cycle begins, right before the DOM is patched and re-rendered. It allows you to get the new state of any reactive data on your component before it actually gets rendered."

“beforeUpdate 钩子在组件上的数据更改之后运行并且更新周期开始,就在 DOM 修补和重新渲染之前。它允许您在实际渲染之前获取组件上任何反应性数据的新状态。”

"The updated hook runs after data changes on your component and the DOM re-renders. If you need to access the DOM after a property change, here is probably the safest place to do it."

“更新的钩子在你的组件上的数据更改和 DOM 重新渲染后运行。如果你需要在属性更改后访问 DOM,这里可能是最安全的地方。”