Vue.js:无法使用 "v-on" 捕获名称中带有点的事件
Vue.js: Unable to catch an event with a point in name using "v-on"
我正在使用 Vue.js (2.6) 和 DataTables.js 并试图捕捉 Page change event.
Datatables 中的页面更改事件被命名为 page.dt
(与所有 DataTables 事件一样,它在点后具有命名空间 dt
)
如果我尝试按照文档来做,它不起作用。
我想,它不起作用,因为 Vue 使用事件名称中的点来定义事件修饰符,例如 click.once
我的问题是:有没有办法使用 Vue 捕获名称中带有点的此类事件?
这里是 HTML 指令:
<table class="table" id="dataTable" v-on:page.dt="pageChange">
这是我的方法pageChange
:
methods: {
pageChange(e) {
var info = datatable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
以下 jQuery 事件处理程序完美运行:
$('#dataTable').on('page.dt', function () {
var info = datatable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
});
<!DOCTYPE html>
<html>
<head>
<title>Vue.js + Datatables.js</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.22/datatables.min.css"/>
</head>
<body class="p-4">
<div class="container fluid">
<div id="app">
<div class="table-responsive-xl">
<table class="table" id="dataTable" v-on:[`page.dt`]="pageChange">
<thead>
<tr>
<th>
Id
</th>
<th>
Name
</th>
<th>
Candy
</th>
<th>
Height
</th>
<th>
Weight
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous">
</script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.22/datatables.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
var datatable = null;
var app = new Vue({
el: "#app",
computed: {
table: function () {
return datatable;
}
},
methods: {
pageChange(e) {
var info = this.table.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
});
datatable = $("#dataTable").DataTable({
ajax: {
url:
"https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json",
dataSrc: "pokemon"
},
columns: [
{ data: "id" },
{ data: "name" },
{ data: "candy" },
{ data: "height" },
{ data: "weight" }
]
});
/* $('#dataTable').on('page.dt', function () {
var info = datatable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
});
*/
</script>
</html>
将 ref="dataTable"
添加到您的 table,并在您的方法中通过 this.$refs.dataTable
访问
<table class="table" id="dataTable" ref="dataTable" v-on:page.dt="pageChange">
methods: {
pageChange(e) {
var info = this.$refs.dataTable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
另一种方法是使用 $event
(我不确定它是否有效,因为无权检查)
<table class="table" id="dataTable" v-on:page.dt="pageChange($event)">
methods: {
pageChange(event) {
var info = event.target.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
您应该能够使用动态参数语法:
v-on:[`page.dt`]="pageChange"
或:
@[`page.dt`]="pageChange"
注意反引号的使用。您不能使用其他形式的引号,因为在属性名称中不允许使用它们。
更新:
我使用 the JSFiddle 提供的进一步调查。
我提供的代码 确实 向 <table>
元素添加了一个 page.dt
事件侦听器。您可以在开发者工具中看到:
因此,如果您想使用 Vue 捕获名称中带有点的事件,那么我建议的代码是正确的。
然而...
这不是这里实际需要的。
page.dt
是命名空间 jQuery 事件。实际事件称为 page
,而不是 page.dt
。 jQuery 将在事件触发但事件本身被调用时按名称空间进行内部过滤 page
。当您使用 jQuery 添加事件 page.dt
时,您会看到它向 DOM:
添加了一个 page
事件
所以您可能认为我们可以通过使用 v-on:page
来解决这个问题。我当然做到了。但可惜没有。
DataTables 调用 jQuery 的 trigger
方法来触发 page.dt
事件。这有两件事:
- 它调用所有通过jQuery注册的监听器。这就是使用 jQuery 示例时
alert
的显示方式。
- 触发原生事件。或者至少,这就是它声称要做的。它实际做的(通过查看 jQuery 代码)是尝试在与事件同名的元素上调用一个方法。对于本机事件可能会很好地工作但对于自定义
page
事件它不会做任何事情。
所以 Vue 无法检测到事件的原因是因为没有 DOM 事件被触发。这都是内部 jQuery 魔法,而不是真正的 DOM 事件。
但是,这确实为我们提供了 Vue-based 解决方法。
鉴于 jQuery 将尝试在元素上调用名为 page
的方法,我们可以为其提供:
:page.prop="pageChange"
我用你的 Fiddle 试过了,确实有效。
我正在使用 Vue.js (2.6) 和 DataTables.js 并试图捕捉 Page change event.
Datatables 中的页面更改事件被命名为 page.dt
(与所有 DataTables 事件一样,它在点后具有命名空间 dt
)
如果我尝试按照文档来做,它不起作用。
我想,它不起作用,因为 Vue 使用事件名称中的点来定义事件修饰符,例如 click.once
我的问题是:有没有办法使用 Vue 捕获名称中带有点的此类事件?
这里是 HTML 指令:
<table class="table" id="dataTable" v-on:page.dt="pageChange">
这是我的方法pageChange
:
methods: {
pageChange(e) {
var info = datatable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
以下 jQuery 事件处理程序完美运行:
$('#dataTable').on('page.dt', function () {
var info = datatable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
});
<!DOCTYPE html>
<html>
<head>
<title>Vue.js + Datatables.js</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.22/datatables.min.css"/>
</head>
<body class="p-4">
<div class="container fluid">
<div id="app">
<div class="table-responsive-xl">
<table class="table" id="dataTable" v-on:[`page.dt`]="pageChange">
<thead>
<tr>
<th>
Id
</th>
<th>
Name
</th>
<th>
Candy
</th>
<th>
Height
</th>
<th>
Weight
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous">
</script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.22/datatables.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
var datatable = null;
var app = new Vue({
el: "#app",
computed: {
table: function () {
return datatable;
}
},
methods: {
pageChange(e) {
var info = this.table.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
});
datatable = $("#dataTable").DataTable({
ajax: {
url:
"https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json",
dataSrc: "pokemon"
},
columns: [
{ data: "id" },
{ data: "name" },
{ data: "candy" },
{ data: "height" },
{ data: "weight" }
]
});
/* $('#dataTable').on('page.dt', function () {
var info = datatable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
});
*/
</script>
</html>
将 ref="dataTable"
添加到您的 table,并在您的方法中通过 this.$refs.dataTable
访问
<table class="table" id="dataTable" ref="dataTable" v-on:page.dt="pageChange">
methods: {
pageChange(e) {
var info = this.$refs.dataTable.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
另一种方法是使用 $event
(我不确定它是否有效,因为无权检查)
<table class="table" id="dataTable" v-on:page.dt="pageChange($event)">
methods: {
pageChange(event) {
var info = event.target.page.info();
alert('Showing page: ' + info.page + ' of ' + info.pages);
}
}
您应该能够使用动态参数语法:
v-on:[`page.dt`]="pageChange"
或:
@[`page.dt`]="pageChange"
注意反引号的使用。您不能使用其他形式的引号,因为在属性名称中不允许使用它们。
更新:
我使用 the JSFiddle 提供的进一步调查。
我提供的代码 确实 向 <table>
元素添加了一个 page.dt
事件侦听器。您可以在开发者工具中看到:
因此,如果您想使用 Vue 捕获名称中带有点的事件,那么我建议的代码是正确的。
然而...
这不是这里实际需要的。
page.dt
是命名空间 jQuery 事件。实际事件称为 page
,而不是 page.dt
。 jQuery 将在事件触发但事件本身被调用时按名称空间进行内部过滤 page
。当您使用 jQuery 添加事件 page.dt
时,您会看到它向 DOM:
page
事件
所以您可能认为我们可以通过使用 v-on:page
来解决这个问题。我当然做到了。但可惜没有。
DataTables 调用 jQuery 的 trigger
方法来触发 page.dt
事件。这有两件事:
- 它调用所有通过jQuery注册的监听器。这就是使用 jQuery 示例时
alert
的显示方式。 - 触发原生事件。或者至少,这就是它声称要做的。它实际做的(通过查看 jQuery 代码)是尝试在与事件同名的元素上调用一个方法。对于本机事件可能会很好地工作但对于自定义
page
事件它不会做任何事情。
所以 Vue 无法检测到事件的原因是因为没有 DOM 事件被触发。这都是内部 jQuery 魔法,而不是真正的 DOM 事件。
但是,这确实为我们提供了 Vue-based 解决方法。
鉴于 jQuery 将尝试在元素上调用名为 page
的方法,我们可以为其提供:
:page.prop="pageChange"
我用你的 Fiddle 试过了,确实有效。