在中後臺系統開發中,訪問任何頁面時,認證是永遠繞不過的檻。以登陸爲例,若是檢測出當前用戶未登陸,會強制跳轉到登陸頁面提示用戶進行登陸。登陸完成後,系統須要跳轉至用戶原先想訪問的頁面。這個過程,暫且稱之爲路由記憶,前面例子中的登陸頁面稱之爲記憶節點。node
由前面的例子咱們不可貴出路由記憶的關鍵邏輯:函數
// 目標頁面 const target = undefined;
但如此只能知足存在一個記憶節點的應用,而實際開發中,咱們可能須要多個記憶節點。當應用中存在多個記憶節點時,問題就會慢慢的浮現。this
接下來,咱們對上面的方案進行擴展。prototype
首先,咱們須要維護一個記憶節點的集合:code
// 記憶節點集合 const nodes = [];
在這以前咱們得先思考一個問題:由記憶節點跳往記憶節點時,是否須要觸發路由記憶?路由
固然不須要!!!開發
當進入記憶節點時,咱們首先得判斷上一個訪問頁面是否爲記憶節點,是則忽略,不然記錄目標頁面。get
在這以前,咱們須要定義一個變量用來記錄上次訪問頁面,這個變量僅記錄上次訪問頁面便可,不管是否爲記憶節點:string
// 上次訪問頁面 const previous = undefined;
爲保證路由記憶結果的質量,咱們須要對每次路由跳轉結束進行監控(不論成功、取消或者失敗)。io
結合前面的例子,咱們如今不可貴出,只有在常規頁面進入記憶節點時,須要對目標頁面進行記錄。
/** * @param to {string} 去往頁面 */ function mark (to) { // 備份上次訪問頁面,防止被覆寫 const backup = previous; // 記錄上次訪問頁面 previous = to; // 若是上一個訪問頁面是記憶節點,中斷函數 if (~nodes.indexOf(backup)) return; // 若是去往頁面不是記憶節點,中斷函數 if (!~nodes.indexOf(to)) return; // 記錄目標頁面 target = backup; }
在每次路由跳轉以前,咱們須要檢測是不是記憶節點進入常規頁面且是否存在目標頁面記錄,若是條件都知足,則打斷原有操做跳往目標頁面,並清空目標頁面記錄。
/** * @param to {string} 去往頁面 */ function check (to) { // 若目標頁面不存在,中斷函數 if (!target) return; // 備份目標頁面,防止在使用以前被清空 const backup = target; // 若是去往頁面是記憶節點,中斷函數 if (~nodes.indexOf(to)) return; // 若是上次訪問不是記憶節點,中斷函數 if (!~nodes.indexOf(previous)) return; // 清空目標記錄 target = undefined; // 路由跳轉,假定執行函數爲 navigate navigate(target); }
var RouterMemory = function (nodes) { // 目標頁面 this.target = undefined; // 上次訪問頁面 this.previous = undefined; // 記憶節點集合 this.nodes = nodes && nodes instanceof Array ? nodes : []; } /** * 記錄上次訪問及目標頁面 * @param to {string} 去往頁面 */ RouterMemory.prototype.mark = function (to) { // 備份上次訪問頁面,防止被覆寫 var backup = this.previous; // 記錄上次訪問頁面 this.previous = to; // 若是上一個訪問頁面是記憶節點,中斷函數 if (~nodes.indexOf(backup)) return; // 若是去往頁面不是記憶節點,中斷函數 if (!~nodes.indexOf(to)) return; // 記錄目標頁面 this.target = backup; } /** * 跳往目標頁面 * @param to {string} 去往頁面 */ RouterMemory.prototype.check = function (to) { // 若目標頁面不存在,中斷函數 if (!this.target) return; // 備份目標頁面,防止在使用以前被清空 const backup = this.target; // 若是去往頁面是記憶節點,中斷函數 if (~nodes.indexOf(to)) return; // 若是上次訪問不是記憶節點,中斷函數 if (!~nodes.indexOf(this.previous)) return; // 清空目標頁面 this.target = undefined; // 路由跳轉,假定執行函數爲 navigate navigate(this.target); }
class RouterMemory { constructor (nodes) { // 目標頁面 this.target = undefined; // 上次訪問頁面 this.previous = undefined; // 記憶節點集合 this.nodes = nodes && nodes instanceof Array ? nodes : []; } /** * @param to {string} 去往頁面 */ mark (to) { // 備份上次訪問頁面,防止被覆寫 const backup = this.previous; // 記錄上次訪問頁面 this.previous = to; // 若是上一個訪問頁面是記憶節點,中斷函數 if (nodes.includes(backup)) return; // 若是去往頁面不是記憶節點,中斷函數 if (!nodes.includes(to)) return; // 記錄目標頁面 this.target = backup; } /** * @param to {string} 去往頁面 */ check (to) { // 若目標頁面不存在,中斷函數 if (!this.target) return; // 備份目標頁面,防止在使用以前被清空 const backup = this.target; // 若是去往頁面是記憶節點,中斷函數 if (nodes.includes(to)) return; // 若是上次訪問不是記憶節點,中斷函數 if (!nodes.includes(this.previous)) return; // 清空目標記錄 this.target = undefined; // 路由跳轉,假定執行函數爲 navigate navigate(this.target); } }