Tôi đã tạo một ứng dụng web sử dụng các phương thức history pushStatevà replaceStateđể điều hướng qua các trang trong khi cập nhật lịch sử.
Kịch bản tự hoạt động gần như hoàn hảo; nó sẽ tải các trang một cách chính xác và ném lỗi trang khi chúng cần được ném. Tuy nhiên, tôi đã nhận thấy một vấn đề kỳ lạ là pushStatesẽ đẩy nhiều mục, trùng lặp (và thay thế các mục trước đó) vào lịch sử.
Ví dụ: giả sử tôi làm như sau (theo thứ tự):
Tải lên index.php (lịch sử sẽ là: Index)
Điều hướng đến profile.php (lịch sử sẽ là: Hồ sơ, Chỉ mục)
Điều hướng đến search.php (lịch sử sẽ là: Tìm kiếm, Tìm kiếm, Lập chỉ mục)
Điều hướng đến dashboard.php
Cuối cùng, đây là những gì sẽ xuất hiện trong lịch sử của tôi (theo thứ tự gần đây nhất đến cũ nhất):
Bảng điều khiển Bảng
điều
khiển Chỉ mục
tìm kiếm
Vấn đề với điều này là khi người dùng nhấp vào nút chuyển tiếp hoặc quay lại, họ sẽ được chuyển hướng đến trang không chính xác hoặc phải nhấp nhiều lần để quay lại một lần. Điều đó, và sẽ vô nghĩa nếu họ đi và kiểm tra lịch sử của họ.
Đây là những gì tôi có cho đến nay:
var Traveller = function(){
this._initialised = false;
this._pageData = null;
this._pageRequest = null;
this._history = [];
this._currentPath = null;
this.abort = function(){
if(this._pageRequest){
this._pageRequest.abort();
}
};
// initialise traveller (call replaceState on load instead of pushState)
return this.init();
};
/*1*/Traveller.prototype.init = function(){
// get full pathname and request the relevant page to load up
this._initialLoadPath = (window.location.pathname + window.location.search);
this.send(this._initialLoadPath);
};
/*2*/Traveller.prototype.send = function(path){
this._currentPath = path.replace(/^\/+|\/+$/g, "");
// abort any running requests to prevent multiple
// pages from being loaded into the DOM
this.abort();
return this._pageRequest = _ajax({
url: path,
dataType: "json",
success: function(response){
// render the page to the dom using the json data returned
// (this part has been skipped in the render method as it
// doesn't involve manipulating the history object at all
window.Traveller.render(response);
}
});
};
/*3*/Traveller.prototype.render = function(data){
this._pageData = data;
this.updateHistory();
};
/*4*/Traveller.prototype.updateHistory = function(){
/* example _pageData would be:
{
"page": {
"title": "This is a title",
"styles": [ "stylea.css", "styleb.css" ],
"scripts": [ "scripta.js", "scriptb.js" ]
}
}
*/
var state = this._pageData;
if(!this._initialised){
window.history.replaceState(state, state.title, "/" + this._currentPath);
this._initialised = true;
} else {
window.history.pushState(state, state.title, "/" + this._currentPath);
}
document.title = state.title;
};
Traveller.prototype.redirect = function(href){
this.send(href);
};
// initialise traveller
window.Traveller = new Traveller();
document.addEventListener("click", function(event){
if(event.target.tagName === "a"){
var link = event.target;
if(link.target !== "_blank" && link.href !== "#"){
event.preventDefault();
// example link would be /profile.php
window.Traveller.redirect(link.href);
}
}
});
Tất cả sự giúp đỡ được đánh giá cao,
Chúc mừng.
updateHistorychức năng của bạn . Bây giờ, updateHistorycó thể được gọi hai lần, lần thứ nhất, khi bạn đang khởi tạo Traveller ( window.Traveller = new Traveller();, constructor-> init-> send-> render-> updateHistory), sau đó cũng redirecttừ từ clickeventListener. Tôi đã không kiểm tra nó, chỉ là phỏng đoán hoang dã, vì vậy thêm nó dưới dạng một nhận xét và không phải là một câu trả lời.