WordPress 如果添加文章瀏覽記錄區域,可以很好的提高網站的用户體驗 比如: 某人經常通過搜索引擎進來我的網站, 可能發現以前在這裏也看過一些文章, 比較合他口味, 久而久之就能發展成常客.
如果懶得看可以直接使用插件:WordPress 文章瀏覽歷史插件
【實現原理】
這個功能實現非常簡單, 平白一點來説就是找個地方將頁面一些信息保存起來, 如果頁面兩次被訪問, 新的內容覆蓋掉舊的內容; 在頁面加載的時候, 將保存的信息取出顯示.
實現方法也很多, 最土的是將內容保存在 cookie 中, 但用 cookie 儲存數據存在一些問題. 比如: cookie 是隨 HTTP 響應一起被髮送的, 會對服務器端響應時間產生一定程度的影響, 尤其是在使用 XMLHttpRequest 對象向服務器端發送或請求數據的時候.
利用 cookie 雖然比較土, 但最實用, 因為幾乎可以兼容所有瀏覽器. 我這裏使用的 localStorage, 數據完全保存在瀏覽器中, 不會有影響服務器響應, 但 IE6/7 中不能使用.
這裏要完成以下幾個功能點:
- 將存儲內容轉成數組對象, 因為 localStorage 只能保存字符串.
- 去重, 如果保存的內容已經存在, 則刪除舊數據, 以最新的為準.
- 限制保存數量, 沒有必要無限保存歷史導致列表超長.
【實現步驟】
我已經寫好了一個名為 View History 的腳本, 不到 50 行代碼, 就是為了實現上述的三個功能.
1. 引用腳本並初始化對象
<script src="view-history.js"></script>
<script>
/* <![CDATA[ */
if(typeof localStorage !== 'undefined' && typeof JSON !== 'undefined') {
var viewHistory = new ViewHistory();
viewHistory.init({
limit: 5,
storageKey: 'viewHistory',
primaryKey: 'url'
});
}
/* ]]> */
</script>
2. 在文章頁面保存瀏覽信息
<script>
/* <![CDATA[ */
// 如果 ViewHistory 的實例存在,則可以將頁面信息寫入。
if(viewHistory) {
var page = {
"title": document.getElementsByTagName('title')[0].innerHTML,
"url": location.href // 這是 primaryKey
// "time": new Date()
// "author": ...
// 這裏可以寫入更多相關內容作為瀏覽記錄中的信息
};
viewHistory.addHistory(page);
}
/* ]]> */
</script>
3. 顯示歷史瀏覽記錄
<script>
/* <![CDATA[ */
var wrap = document.getElementById('view-history');
// 如果 ViewHistory 的實例存在,並且外層節點存在,則可顯示歷史瀏覽記錄
if(viewHistory && wrap) {
// 獲取瀏覽記錄
var histories = viewHistory.getHistories();
// 組裝列表
var list = document.createElement('ul');
if(histories && histories.length > 0) {
for(var i=histories.length-1; i>=0; i--) {
var history = histories[i];
var item = document.createElement('li');
var link = document.createElement('a');
link.href = history.url;
link.innerHTML = history.title;
item.appendChild(link);
list.appendChild(item);
}
// 插入頁面特定位置
wrap.appendChild(list);
}
}
/* ]]> */
</script>
【説明】
只用 localStorage 做歷史瀏覽記錄不能解決時效性問題, 也就是不能獲得最新的文章信息. 如果我將文章評論數加到瀏覽記錄中, 那麼用户看到的僅是他訪問當時的評論數量. 解決辦法是有的, 有些網站只保存文章的 ID, 在頁面加載時再動態加載文章信息, 比如: 評論數和平均評價.
附完整代碼:
ViewHistory = function() {
this.config = {
limit: 10,
storageKey: 'viewHistory',
primaryKey: 'url'
};
this.cache = {
localStorage: null,
userData: null,
attr: null
};
};
ViewHistory.prototype = {
init: function(config) {
this.config = config || this.config;
var _self = this;
// define localStorage
if (!window.localStorage && (this.cache.userData = document.body) && this.cache.userData.addBehavior && this.cache.userData.addBehavior('#default#userdata')) {
this.cache.userData.load((this.cache.attr = 'localStorage'));
this.cache.localStorage = {
'getItem': function(key) {
return _self.cache.userData.getAttribute(key);
},
'setItem': function(key, value) {
_self.cache.userData.setAttribute(key, value);
_self.cache.userData.save(_self.cache.attr);
}
};
} else {
this.cache.localStorage = window.localStorage;
}
},
addHistory: function(item) {
var items = this.getHistories();
for(var i=0, len=items.length; i<len; i++) {
if(item[this.config.primaryKey] && items[i][this.config.primaryKey] && item[this.config.primaryKey] === items[i][this.config.primaryKey]) {
items.splice(i, 1);
break;
}
}
items.push(item);
if(this.config.limit > 0 && items.length > this.config.limit) {
items.splice(0, 1);
}
var json = JSON.stringify(items);
this.cache.localStorage.setItem(this.config.storageKey, json);
},
getHistories: function() {
var history = this.cache.localStorage.getItem(this.config.storageKey);
if(history) {
return JSON.parse(history);
}
return [];
}
};