日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
前端路由與單頁頁面實踐

??想了解更多內(nèi)容,請訪問:??

??和華為官方合作共建的鴻蒙技術(shù)社區(qū)??

??https://ost.??

路由就是指隨著瀏覽器地址欄的變化,展示給用戶的頁面也不相同。

傳統(tǒng)的網(wǎng)頁根據(jù)用戶訪問的不同的地址,瀏覽器從服務(wù)器獲取對應(yīng)頁面的內(nèi)容展示給用戶。這樣容易造成服務(wù)器壓力比較大,而且用戶訪問速度也比較慢,在這種場景下,出現(xiàn)了單頁應(yīng)用。

路由的實現(xiàn)方式

  1. location.hash+hashchange事件。
  2. history.pushState()+popState事件。

實現(xiàn)主要基于以下幾個方面的特性

  1. URL 中的 hash 值只是客戶端的一種狀態(tài),也就是說當向服務(wù)器發(fā)出請求時,hash 部分不會被發(fā)送。
  2. hash 值的改變,都會在瀏覽器的訪問歷史中增加一個記錄,因此我們能通過瀏覽器的回退,前進按鈕控制 hash 的切換。
  3. 可以通過設(shè)置a標簽,并通過設(shè)置 href 屬性,例如href = ‘#/blue’,當點擊標簽的時候,url的 hash 。值會發(fā)生改變,在當前url的后面增加上’#/blue’, 同時觸發(fā)hashchange,再回調(diào)函數(shù)中進行處理。
  4. 前進后退的時候,可以直接通過js來對 location.hash 進行賦值,改變url的 hash 值,例如 location.hash = ‘#/blue’即可,此時url會改變, 也會觸發(fā)hashchange事件。
  5. 因此我們可以使用 hashchange 事件來監(jiān)聽 hash 值得變化,從而對頁面進行跳轉(zhuǎn)(渲染)。

hash模式

hash方法是在路由中帶有一個#,主要原理是通過監(jiān)聽#后的 URL 路徑標識符的更改而觸發(fā)的瀏覽器hashchange事件,然后通過獲取location.hash 得到當前的路徑標識符,再進行一些路由跳轉(zhuǎn)的操作。hash方法的push本身會記錄你的點擊記錄,當你想要通過返回按鈕返回時,它會根據(jù)你的點擊記錄用到replace來解決。

先建立一個index.html文件,在body標簽中開始hash的編寫:

// index.html






前端路由


hello , Hash router!!!







然后引用js文件處理router里面的邏輯:

// hash.js
class Router {
constructor() {
/**
* 以鍵值對的形式存儲路由
*/
this.routers = new Object();
/**
* 當前路由的URL
*/
this.currentUrl = "";
/**
* 記錄出現(xiàn)過的hash
*/
this.history = [];
/**
* 作為指針,默認指向this.history的末尾,根據(jù)后退前進指向history中不同的hash
*/
this.currentIndex = this.history.length - 1;
/**
* 默認不是后退操作
*/
this.isBack = false;
}
/**
* 都定義在原型上,后面的覆蓋前面的,這個不執(zhí)行
*/
route(path, callback) {
console.log(1);
}
}
/**
* 將路由的hash以及對應(yīng)的callback函數(shù)儲存
* @param {*} path
* @param {*} callback
*/
Router.prototype.route = function (routes) {
for (let route of routes) {
this.routers[route.path] = route.callback || function () { };
}
};

/**
* 當頁面刷新的時候
*/
Router.prototype.refresh = function () {
/**
* 獲取當前頁面中的hash路徑
*/
this.currentUrl = window.location.hash.slice("1") || "/";
/**
* 不是后退才執(zhí)行
*/
if (!this.isBack) {
if (this.currentIndex < this.history.length - 1)
this.history = this.history.slice(0, this.currentIndex + 1);
/**
* 將當前hash路由推入數(shù)組儲存,指針向前移動
*/
this.history.push(this.currentUrl);
this.currentIndex++;
}
this.isBack = false;
/**
* 執(zhí)行當前hash路徑的回調(diào)函數(shù)
*/
this.routers[this.currentUrl]();
console.log("refresh");
console.log(this.history);
console.log(this.currentIndex);
};
/**
* 當頁面后退,回退的過程中會觸發(fā)hashchange,將hash重新放入,索引增加
*/
Router.prototype.back = function () {
console.log("back");
console.log(this.history);
console.log(this.currentIndex);
// 后退操作設(shè)置為true
this.isBack = true;
/**
* 如果指針小于0的話就不存在對應(yīng)hash路由了,因此鎖定指針為0即可
*/
this.currentIndex <= 0
? (this.currentIndex = 0)
: (this.currentIndex = this.currentIndex - 1);
/**
* 隨著后退,location.hash也應(yīng)該隨之變化
* 并執(zhí)行指針目前指向hash路由對應(yīng)的callback
*/
location.hash = `#${this.history[this.currentIndex]}`;
this.routers[this.history[this.currentIndex]]();
};
/**
* 初始化,監(jiān)聽頁面的加載與hash值的變化
*/
Router.prototype.init = function () {
/**
* 修改this指向,否則指向window
*/
window.addEventListener("load", this.refresh.bind(this), false);
window.addEventListener("hashchange", this.refresh.bind(this), false);
};
// 監(jiān)聽hash模式路由
Router.prototype.eventHashRouter = function() {
// 監(jiān)聽load事件,防止刷新頁面數(shù)據(jù)丟失
window.addEventListener("load", this.hashRouter.bind(this));
window.addEventListener("hashchange", this.hashRouter.bind(this))
}
//replace模式頁面跳轉(zhuǎn)
Router.prototype.replace = function(url) {
url = "#" +url;
window.location.replace(url);
}
const route = new Router();
/**
* 初始化
*/
route.init();
const routes = [
{
path: "/",
callback: function () {
let el = document.body;
el.style.backgroundColor = "#fff";
},
},
{
path: "/blue",
callback: function () {
let el = document.body;
el.style.backgroundColor = "blue";
},
},
{
path: "/green",
callback: function () {
let el = document.body;
el.style.backgroundColor = "green";
},
},
{
path: "/red",
callback: function () {
let el = document.body;
el.style.backgroundColor = "red";
},
},
{
path: "/orange",
callback: function () {
let el = document.body;
el.style.backgroundColor = "orange";
},
},
];
/**
* 將hash值與cb綁定
*/
route.route(routes);
window.onload = function () {
let btn = document.getElementById("btn");
btn.addEventListener("click", route.back.bind(route), false);
};

history模式

HistoryAPI來實現(xiàn)URL的變化,其中最主要用history.pushState()新增一個歷史記錄,用history.replaceState()直接替換當前歷史記錄,可以在不進行刷新的情況下,操作瀏覽器的歷史記錄。需要后臺配置支持,因為我們的應(yīng)用是個單頁的客戶端應(yīng)用,如果后臺沒有正確的配置,當用戶在瀏覽器直接訪問一些沒有配置的路徑就會返回404,但因為沒有#號,所以當用戶刷新頁面之類的操作時,瀏覽器還是會給服務(wù)器發(fā)送請求。為了避免出現(xiàn)這種情況,所以這個實現(xiàn)需要服務(wù)器的支持,需要定向到根路徑。html5 提供了historyAPI來實現(xiàn)URL的變化,其中最主要的 API 有以下兩個:

  1. history.pushState()新增一個歷史記錄。
  2. history.replaceState() 直接替換當前歷史記錄。
  3. 相同點:可以在不進行刷新的情況下,操作瀏覽器的歷史記錄。
  4. 先建立一個index.html文件,在body標簽中開始history的編寫:






前端路由


hello , History router!!!







然后引用js文件處理router里面的邏輯:

// history.js
/**
* history路由
*/
class Router {
constructor() {
/**
* 以鍵值對的形式存儲路由
*/
this.routers = new Object();
}
}

/**
* 監(jiān)聽頁面的popstate事件
*/
Router.prototype.bindPopState = function (e) {
const path = e.state && e.state.path;
this.routers[path] && this.routers[path]();
};

/**
* 將路由的path以及對應(yīng)的callback函數(shù)儲存
* @param {*} path
* @param {*} callback
*/
Router.prototype.route = function (routes) {
for (let route of routes) {
this.routers[route.path] = route.callback || function () { };
}
};

/**
* 初始化,直接替換當前歷史紀錄,并用狀態(tài)對象進行存儲
*/
Router.prototype.init = function (path) {
window.history.replaceState({ path: path }, null, path);
this.routers[path] && this.routers[path]();
/**
* 加入事件監(jiān)聽
*/
window.addEventListener("popstate", this.bindPopState.bind(this), false);
};

/**
* 更新頁面,新增一個歷史紀錄
*/
Router.prototype.go = function (path) {
window.history.pushState({ path: path }, null, path);
this.routers[path] && this.routers[path]();
};

const route = new Router();
route.init(window.location.href);
const routes = [
{
path: "http://127.0.0.1:5500/",
callback: function () {
let el = document.body;
el.style.backgroundColor = "#fff";
},
},
{
path: "http://127.0.0.1:5500/color/blue",
callback: function () {
let el = document.body;
el.style.backgroundColor = "blue";
},
},
{
path: "http://127.0.0.1:5500/color/green",
callback: function () {
let el = document.body;
el.style.backgroundColor = "green";
},
},
{
path: "http://127.0.0.1:5500/color/red",
callback: function () {
let el = document.body;
el.style.backgroundColor = "red";
},
},
{
path: "http://127.0.0.1:5500/color/orange",
callback: function () {
let el = document.body;
el.style.backgroundColor = "orange";
},
},
];
/**
* 將hash值與cb綁定
*/
route.route(routes);
/**
* a標簽會跳轉(zhuǎn)頁面,阻止
*/
window.addEventListener(
"click",
function (e) {
var e = e || window.event;
var target = e.target || e.srcElement;
if ((target.tagName = "A")) {
e.preventDefault();
route.go(e.target.getAttribute("href"));
}
},
false
);

總結(jié)

本文講解了路由的核心實現(xiàn)原理,但是結(jié)合具體框架后,框架增加了很多特性,如動態(tài)路由、路由參數(shù)、路由動畫等等,這些導(dǎo)致路由實現(xiàn)變的復(fù)雜。本文去粗取精只針對前端路由最核心部分的實現(xiàn)進行分析,并基于 hash 和 history 兩種模式,頁面加載時,它可能有一個非空狀態(tài)對象。例如,如果頁面設(shè)置了一個狀態(tài)對象(使用pushState()or replaceState())然后用戶重新啟動他們的瀏覽器,當頁面重新加載時,頁面將收到一個onload事件,雖沒有popstate事件,但是將獲得加載的狀態(tài)對象。

??想了解更多內(nèi)容,請訪問:??

??和華為官方合作共建的鴻蒙技術(shù)社區(qū)??

??https://ost.??


分享文章:前端路由與單頁頁面實踐
文章源于:http://www.5511xx.com/article/dpoidhc.html