- 项目里使用
laravel-admin
搭建后台, 然后做了一个小功能, 右上角增加一个消息通知
- 如上图, 右上角有一个小铃铛, 点击之后清空消息, 并刷新当前页面. 使用的是
laravel-admin
的action
去操作
<?php
namespace App\Admin\Actions\Custom;
use Encore\Admin\Actions\Action;
use Illuminate\Http\Request;
class MarkNotificationRead extends Action
{
protected $selector = '.mark-notification-read';
public function handle(Request $request)
{
// forget notifications
return $this->response()->success("已读所有消息")->refresh();
}
public function html()
{
// get notifications
$count = 1;
$countText = "<span class=\"label label-danger\">{$count}</span>";
return "<li title='点击标记为已读'>
<a href=\"#\" class='mark-notification-read'>
<i data-count='{$count}' id='notification' class=\"fa fa-bell fa-rotate-0\"></i>
{$countText}
</a>
</li>";
}
}
-
如上伪代码实现了一个通知, 当用户点击按钮的时候会触发
handle
方法,然后刷新当前页面 -
但是由于
laravel-admin
采用pjax
导致无法刷新整个页面, 只会刷新下方的内容页面, 所以即使点击了也无法使小铃铛的1
变成`` -
看了文档, 在
handle
方法使用\Admin::disablePjax();
禁用pjax
, 不生效(应该在页面级别加,而不是处理的方法) -
之后查看了一下
MarkNotificationRead
继承的Action
有一个方法- 之前思维一直卡在
pjax
了, 一直没想到在Action
处理 - 总是想着应该在页面级别处理
pjax
- 之前思维一直卡在
-
父类中的
handleActionPromise
是处理ajax
请求之后的handle
, 随后重写父类的方法handleActionPromise
public function handleActionPromise()
{
$resolve = <<<'SCRIPT'
var actionResolver = function (data) {
var response = data[0];
var target = data[1];
console.log(data);
if (typeof response !== 'object') {
return $.admin.swal({type: 'error', title: 'Oops!'});
}
var then = function (then) {
if (then.action == 'refresh') {
// 增加这一行代码
window.location.reload();
return;
}
if (then.action == 'download') {
window.open(then.value, '_blank');
}
if (then.action == 'redirect') {
$.admin.redirect(then.value);
}
if (then.action == 'location') {
window.location = then.value;
}
if (then.action == 'open') {
window.open(then.value, '_blank');
}
};
if (typeof response.html === 'string') {
target.html(response.html);
}
if (typeof response.swal === 'object') {
$.admin.swal(response.swal);
}
if (typeof response.toastr === 'object' && response.toastr.type) {
$.admin.toastr[response.toastr.type](response.toastr.content, '', response.toastr.options);
}
if (response.then) {
then(response.then);
}
};
var actionCatcher = function (request) {
if (request && typeof request.responseJSON === 'object') {
$.admin.toastr.error(request.responseJSON.message, '', {positionClass:"toast-bottom-center", timeOut: 10000}).css("width","500px")
}
};
SCRIPT;
\Encore\Admin\Admin::script($resolve);
return <<<'SCRIPT'
process.then(actionResolver).catch(actionCatcher);
SCRIPT;
}
- 在
handle
增加了一个window.location.reload();
, 处理起来比较复杂 - 相比之下
Dcat Admin
在这方面做得很多,直接在Action
类重写父类方法
/**
* 设置动作发起请求前的回调函数,返回false可以中断请求.
*
* @return string
*/
protected function actionScript()
{
// 发起请求之前回调,返回false可以中断请求
return <<<'JS'
function (data, target, action) { }
JS;
}
/**
* 设置请求成功回调,返回false可以中断默认的成功处理逻辑.
*
* @return string
*/
protected function resolverScript()
{
// 请求成功回调,返回false可以中断默认的成功处理逻辑
return <<<'JS'
function (target, results) {}
JS;
}
/**
* 处理接口返回的HTML代码.
*
* @return string
*/
protected function handleHtmlResponse()
{
return <<<'JS'
function (target, html, data) {
target.html(html);
}
JS;
}
/**
* 设置请求出错回调,返回false可以中断默认的错误处理逻辑.
*
* @return string
*/
protected function rejectScript()
{
return <<<'JS'
function (target, results) {}
JS;
}
总结
- 处理问题而不要直接凭感官觉得是某部分出问题(当然后时候也应该这样子)
- 一开始总觉得是
PJAX
的问题, 就一直绕进去了.
- 一开始总觉得是
- 当用这个方式无法解决问题的时候, 是继续深究还是换一个思路
- 这个没办法得出结论, 可能深究之后也有答案, 换个方式也有答案
- 可能就是一个度的问题