正确实施 Vue.js + DataTables
Implementing Vue.js + DataTables properly
我正在尝试实现 Vue.js + jQuery 的数据表,但发生了奇怪的事情。
在 Firefox 上检查 fiddle (不适用于 chrome):
http://jsfiddle.net/chrislandeza/xgv8c01y/
当我更改 DataTable 的状态(例如排序、搜索等)时:
- 列表中新增数据消失
- DOM 没有读取指令或 vue 属性
我很确定任何尝试混合 vue.js+数据表的人都遇到过这个问题。你做了什么来解决这个问题?
或者是否存在与 jquery 的 DataTable 具有相同(或接近)功能的纯 Vue.js script/plugin? (分页、搜索、排序、要显示的条目数等)。
这是上面 fiddle 中的代码:
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:
$(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);
}
}
});
非常感谢任何建议。
要使 DataTables 插件与 Vue 正确集成,请记住以下几点:
根据您的示例,如果您已经准备好数据并呈现给 DOM,则可以使用 var dT = $('#app-datatable').DataTable();
来初始化数据表。如果您没有完全呈现 DOM <table></table>
(可能是由于通过延迟 ajax 调用填充了数据),则在数据准备好之前无法初始化数据表。例如,如果您的组件中有一个 fetchData
方法,您可以在承诺完成后初始化 DataTable。
要更新table一旦初始化,可能是由于底层table数据发生变化,最好的(也许是唯一的方法)是先销毁table,在 Vue 接收新数据并将其写入 DOM 之前:
var dT = $('#app-datatable').DataTable();
dT.destroy();
然后,一旦数据(在您的例子中是用户数组)被更新,
像这样重新初始化数据表:
this.$nextTick(function() {
$('#app-datatable').DataTable({
// DataTable options here...
});
})
$nextTick 是确保 Vue 在重新初始化之前将新数据刷新到 DOM 所必需的。如果在DataTable插件初始化后更新DOM,你会看到table的数据,但是通常的排序,分页等是行不通的。
另一个重要的一点,是在你的数据集中有一个行id,并在<tr></tr>
:
中设置键
<tr v-repeat="user: users" track-by="id">
如果没有 track-by
,Vue 在 DataTables 初始化后将新数据刷新到 DOM 时会报错,可能是因为没有找到被 DataTables 劫持的 DOM 元素。
也许你可以使用生命周期钩子,事实上这些奇怪的事情是由操纵 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();
})
}
});
我已经从外部提供了 table 数据(不是来自 DataTable
的 Ajax 调用)并且仅使用这些生命周期挂钩来销毁/重新创建 table 是有效的对我来说:
beforeUpdate: function() {
if (this.dataTable) {
this.dataTable.destroy()
}
},
updated: function() {
this.dataTable = $(this.$el).DataTable()
}
来自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."
"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."
我正在尝试实现 Vue.js + jQuery 的数据表,但发生了奇怪的事情。
在 Firefox 上检查 fiddle (不适用于 chrome):
http://jsfiddle.net/chrislandeza/xgv8c01y/
当我更改 DataTable 的状态(例如排序、搜索等)时:
- 列表中新增数据消失
- DOM 没有读取指令或 vue 属性
我很确定任何尝试混合 vue.js+数据表的人都遇到过这个问题。你做了什么来解决这个问题?
或者是否存在与 jquery 的 DataTable 具有相同(或接近)功能的纯 Vue.js script/plugin? (分页、搜索、排序、要显示的条目数等)。
这是上面 fiddle 中的代码:
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:
$(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);
}
}
});
非常感谢任何建议。
要使 DataTables 插件与 Vue 正确集成,请记住以下几点:
根据您的示例,如果您已经准备好数据并呈现给 DOM,则可以使用
var dT = $('#app-datatable').DataTable();
来初始化数据表。如果您没有完全呈现 DOM<table></table>
(可能是由于通过延迟 ajax 调用填充了数据),则在数据准备好之前无法初始化数据表。例如,如果您的组件中有一个fetchData
方法,您可以在承诺完成后初始化 DataTable。要更新table一旦初始化,可能是由于底层table数据发生变化,最好的(也许是唯一的方法)是先销毁table,在 Vue 接收新数据并将其写入 DOM 之前:
var dT = $('#app-datatable').DataTable(); dT.destroy();
然后,一旦数据(在您的例子中是用户数组)被更新, 像这样重新初始化数据表:
this.$nextTick(function() { $('#app-datatable').DataTable({ // DataTable options here... }); })
$nextTick 是确保 Vue 在重新初始化之前将新数据刷新到 DOM 所必需的。如果在DataTable插件初始化后更新DOM,你会看到table的数据,但是通常的排序,分页等是行不通的。
另一个重要的一点,是在你的数据集中有一个行id,并在
中设置键<tr></tr>
:<tr v-repeat="user: users" track-by="id">
如果没有
track-by
,Vue 在 DataTables 初始化后将新数据刷新到 DOM 时会报错,可能是因为没有找到被 DataTables 劫持的 DOM 元素。
也许你可以使用生命周期钩子,事实上这些奇怪的事情是由操纵 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();
})
}
});
我已经从外部提供了 table 数据(不是来自 DataTable
的 Ajax 调用)并且仅使用这些生命周期挂钩来销毁/重新创建 table 是有效的对我来说:
beforeUpdate: function() {
if (this.dataTable) {
this.dataTable.destroy()
}
},
updated: function() {
this.dataTable = $(this.$el).DataTable()
}
来自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."
"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."