AJAX 事件处理程序是 AJAX 框架与服务器通信的 API 端点。它们可以响应原始数据、重定向浏览器或动态更新页面上的局部内容。
要创建 AJAX 处理程序,将其定义为 PHP 函数在页面、局部或布局的 PHP 部分中,或在 CMS 组件中。处理程序名称应使用onSomething模式,例如,onName。所有处理程序都支持使用更新局部作为 AJAX 请求的一部分。
function onSubmitContactForm()
{
// ...
}如果在页面和布局中同时定义了两个同名处理程序,则页面处理程序将优先。在组件中定义的处理程序优先级最低。
每个 AJAX 请求都应指定一个处理程序名称,可以使用 数据属性 API 或 JavaScript API。发出请求时,服务器将搜索所有已注册的处理程序并定位它找到的第一个。
<!-- Attributes API -->
<button data-request="onSubmitContactForm">Go</button>
<!-- JavaScript API -->
<script> oc.ajax('onSubmitContactForm') </script>页面、布局和组件定义的处理程序都会自动注册。如果你正在从局部视图(partial)内部调用处理程序,请使用 {% ajaxPartial %} Twig 标签,它会调整页面生命周期以注册其处理程序。
当 AJAX 请求在 HTML 表单标签内发生时,表单的所有输入值都可供处理程序使用。在下面的示例中,first_name 的值将随请求一起发送。
<form id="myForm">
<input name="first_name" />
<button data-request="onSubmitContactForm">Go</button>
</form>JavaScript API 通过 oc.request 函数支持此逻辑.
<script> oc.request('#myForm', 'onSubmitContactForm') </script>您可以使用 input() PHP 函数来访问该变量。
function onSubmitContactForm()
{
$firstName = input('first_name');
}有时你可能需要发起一个 AJAX 请求,仅仅是为了更新页面内容,而不需要执行任何代码。你可以使用 onAjax 处理程序来实现此目的。此处理程序随处可用,而无需编写任何代码。
<button data-request="onAjax">Do nothing</button>如果两个组件注册了相同的处理程序名称,建议使用组件短名称或别名来作为处理程序的前缀。如果一个组件使用了别名mycomponent,则该处理程序可以通过mycomponent::onName来定位。
<button data-request="mycomponent::onSubmitContactForm">Go</button>参阅 组件开发文章 了解更多。
如果您需要将浏览器重定向到另一个位置,请从 AJAX 处理程序返回 Redirect 响应对象。框架将在响应从服务器返回后立即重定向浏览器。带重定向的 AJAX 处理程序示例。
function onRedirectMe()
{
return Redirect::to('http://google.com');
}AJAX处理程序的响应可以通过返回结构化数据来作为可消费的API。如果AJAX处理程序返回一个数组,您可以在 success 事件处理程序中访问其元素。返回数据对象的示例AJAX处理程序。
function onFetchDataFromServer()
{
// Some server-side code
return [
'totalUsers' => 1000,
'totalProjects' => 937
];
}数据可以通过数据属性API获取。
<form data-request="onHandleForm" data-request-success="console.log(data)">与 JavaScript API 相同。
<form onsubmit="oc.request(this, 'onHandleForm', {
success: function(data) {
console.log(data);
}
}); return false"
>有时您可能希望代码在处理程序执行之前运行。将 onInit 函数定义为 布局执行生命周期 的一部分,允许代码在每个 AJAX 处理程序之前运行。
function onInit()
{
// From a page or layout PHP code section
}您可以在 CMS 组件类 中定义一个 init 方法。
function init()
{
// From a component or widget class
}你可以使用 AjaxException 类来抛出 AJAX 异常,以便将响应视为错误,同时保留正常发送响应内容的能力。只需将响应内容作为异常的第一个参数传递即可。
throw new AjaxException([
'error' => 'Not enough questions',
'questionsNeeded' => 2
]);这些错误由 AJAX 框架处理。
<form data-request="onHandleForm" data-request-error="console.log(data)">JavaScript API 也一样。
<form onsubmit="oc.request(this, 'onHandleForm', {
error: function(data) {
console.log(data);
}
}); return false"
>抛出此异常类型时 局部视图将更新 照常
派发事件会在 AJAX 响应中被触发,在请求完成之后且在局部视图更新之前。
您可以使用dispatchBrowserEvent方法从AJAX处理器分派JavaScript事件。此方法接受任何事件名称(第一个参数)以及要传递给事件的详细变量(第二个参数),这些变量必须兼容JSON序列化。
function onPerformAction()
{
$this->dispatchBrowserEvent('app:update-profile');
$this->dispatchBrowserEvent('app:update-profile', ['name' => 'Jeff']);
}在浏览器中,使用 addEventListener 监听 AJAX 请求完成时分派的事件。事件变量可通过 event.detail 对象获取。
addEventListener('app:update-profile', function (event) {
alert('Profile updated with name: ' + event.detail.name);
});例如,如果您想显示一个警告,表明文档已被另一用户更新,您可以向浏览器分派一个事件并抛出一个 AjaxException 以中止该进程。
AjaxException和ValidationException是支持分发事件的终止异常。
public function onUpdate()
{
$this->dispatchBrowserEvent('app:stale-document');
throw new AjaxException;
}您可以使用通用监听器在浏览器中监听此事件. 此示例在重新提交请求之前提示用户,并在数据中设置 force 标志.
addEventListener('app:stale-document', function (event) {
if (confirm('Another user has updated this document, proceed?')) {
oc.request(event.target, 'onUpdate', { data: {
force: true
}});
}
});为了防止局部内容作为响应的一部分进行更新,请在事件对象上调用 preventDefault()。
addEventListener('app:stale-document', function (event) {
event.preventDefault();
});