是一個函數(shù),返回當前頁面的 pjax-version,即頁面中 標簽內容。使用 response.setHeader(“X-PJAX-Version”, “”) 設置與當前頁面不同的版本號,可強制頁面跳轉而不是局部刷新scrollTo0頁面加載后垂直滾動距離(與原頁面保持一致可使過度效果更平滑)type“GET”ajax 的參數(shù),http 請求方式dataType“html”ajax 的參數(shù),響應內容的 Content-Typecontainer
用于查找容器的 CSS 選擇器,[container] 參數(shù)沒有指定時使用urllink.href要跳轉的連接,默認 a 標簽的 href 屬性fragment
使用響應內容的指定部分(css 選擇器)填充頁面,服務端不進行處理導致全頁面請求的時候需要使用該參數(shù),簡單的說就是對請求到的頁面做截取pjax事件
為了方便擴展,pjax 支持一些預定義的事件。
pjax:click?options點擊按鈕時觸發(fā)??烧{用 e.preventDefault() 取消 pjaxapjax:beforeSend?xhr, optionsajax 執(zhí)行 beforeSend 函數(shù)時觸發(fā),可在回調函數(shù)中設置額外的請求頭參數(shù)??烧{用 e.preventDefault() 取消 pjaxpjax:start
xhr, optionspjax 開始(與服務器連接建立后觸發(fā))pjax:send
xhr, optionspjax:start之后觸發(fā)pjax:clicked
optionsajax 請求開始后觸發(fā)pjax:beforeReplace
contents, optionsajax請求成功,內容替換渲染前觸發(fā)pjax:success
data, status, xhr, options內容替換成功后觸發(fā)pjax:timeout?xhr, optionsajax 請求超時后觸發(fā)??烧{用 e.preventDefault() 繼續(xù)等待 ajax 請求結束pjax:error?xhr, textStatus, error, optionsajax 請求失敗后觸發(fā)。默認失敗后會跳轉 url,如要阻止跳轉可調用 e.preventDefault()pjax:complete
xhr, textStatus, optionsajax請求結束后觸發(fā),不管成功還是失敗pjax:end
xhr, optionspjax所有事件結束后觸發(fā)pjax:popstate
forward / back(前進/后退)pjax:start
null, optionspjax開始pjax:beforeReplace
contents, options內容替換渲染前觸發(fā),如果緩存了要導航頁面的內容則使用緩存,否則使用pjax加載pjax:end
null, optionspjax結束
客戶端通過以下 2 個步驟就可以使用 pjax :
引入jquery 和 jquery.pjax.js注冊事件JS
<script src="jquery.pjax.js"></script>
/**
* 方式1 監(jiān)聽按鈕父節(jié)點事件
*/
$(document).pjax(selector, [container], options);
/**
* 方式2 直接監(jiān)聽按鈕,可以不用指定容器,默認使用按鈕的data-pjax屬性值查找容器
*/
$("a[data-pjax]").pjax();
/**
* 方式3 主動綁定點擊事件監(jiān)聽
*/
$(document).on('click', 'a', $.pjax.click);
$(document).on('click', 'a', function(event) {
//獲取container
var container = $(this).closest('[data-pjax-container]');
//click回調
$.pjax.click(event, container);
});
/**
* 方式4 主動綁定表單提交事件監(jiān)聽
*/
$(document).on('submit', 'form', function(event) {
//獲取container
var container = $(this).closest('[data-pjax-container]');
//submit回調
$.pjax.submit(event, container);
});
/**
* 方式5 加載內容到指定容器
*/
$.pjax({url: this.href, container: '#main'});
/**
* 方式6 重新加載當前頁面容器的內容
*/
$.pjax.reload('#container');
YII
在 Yii 中,已經(jīng)將 pjax 封裝成了 widgets,故在渲染時如下使用即可:
//view <?php Pjax::begin(); ?> ... ... <?php Pjax::end(); ?>
pjax 封裝成的 widgets 源碼文件widgets/Pjax.php ,事件注冊部分如下:
public function registerClientScript()
{
//a標簽的click
if ($this->linkSelector !== false) {
$linkSelector = Json::htmlEncode($this->linkSelector !== null ? $this->linkSelector : '#' . $id . ' a');
$js .= "jQuery(document).pjax($linkSelector, \\\\"#$id\\\\", $options);";
}
//form表單的submit
if ($this->formSelector !== false) {
$formSelector = Json::htmlEncode($this->formSelector !== null ? $this->formSelector : '#' . $id . ' form[data-pjax]');
$submitEvent = Json::htmlEncode($this->submitEvent);
$js .= "\\\\njQuery(document).on($submitEvent, $formSelector, function (event) {jQuery.pjax.submit(event, '#$id', $options);});";
}
$view->registerJs($js);
}
服務端
由于只是 HTML5 支持 pjax,所以后端需要做兼容處理。通過 X-PJAX 頭信息可得知客戶端是否支持 pjax,如果支持,則只返回局部頁面,否則 a 鏈接默認跳轉,返回整個頁面。
/**
* IndexController示例
*/
public function actionIndex() {
$dataProvider = new CActiveDataProvider('Article', array(
'criteria' => array('order' => 'create_time DESC')
));
//存在X-Pjax頭,支持pjax
if (Yii::$app->getRequest()->getHeaders()->get('X-Pjax')) {
//返回局部頁面
$this->renderPartial('index', array(
'dataProvider' => $dataProvider,
));
} else {
//返回整個頁面
$this->render('index', array(
'dataProvider' => $dataProvider,
));
}
}
pjax失效情況
在以下 9 種情況時候 pjax 會失效,源碼部分如下:
//click回調
function handleClick(event, container, options) {
...
// 1. 點擊的事件源不是a標簽。a標簽可以對舊版本瀏覽器的兼容,因此不建議使用其他標簽注冊事件
if (link.tagName.toUpperCase() !== 'A')
throw "$.fn.pjax or $.pjax.click requires an anchor element"
// 2. 使用鼠標滾輪點擊、點擊超鏈接的同時按下Shift、Ctrl、Alt和Meta
if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
return
// 3. 跨域
if (location.protocol !== link.protocol || location.hostname !== link.hostname)
return
// 4. 當前頁面的錨點定位
if (link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location))
return
// 5. 已經(jīng)阻止元素發(fā)生默認的行為
if (event.isDefaultPrevented())
return
...
var clickEvent = $.Event('pjax:click')
$(link).trigger(clickEvent, [opts])
// 6. pjax:click事件回調中已經(jīng)阻止元素發(fā)生默認的行為
if (!clickEvent.isDefaultPrevented()) {
pjax(opts)
}
}
//pjax
function pjax(options) {
options.beforeSend = function(xhr, settings) {
//7. ajx超時
timeoutTimer = setTimeout(function() {
if (fire('pjax:timeout', [xhr, options]))
xhr.abort('timeout')
}, settings.timeout)
}
options.success = function(data, status, xhr) {
//8. 當前頁面和請求的新頁面版本不一致
if (currentVersion && latestVersion && currentVersion !== latestVersion) {
return
}
//9. ajax失敗
context.html(container.contents)
}
其他方案
除了使用 pjax 解決局部刷新并支持前進和后退問題外,也可以使用 browserstate/history.js ajax 方案來實現(xiàn)
推薦教程:《PHP》《JS教程》
更多關于云服務器,域名注冊,虛擬主機的問題,請訪問西部數(shù)碼官網(wǎng):m.ps-sw.cn