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

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

新聞中心

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

??想了解更多內(nèi)容,請(qǐng)?jiān)L問:??

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

??https://ost.??

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

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

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

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

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

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

hash模式

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

先建立一個(gè)index.html文件,在body標(biāo)簽中開始hash的編寫:

// index.html






前端路由


hello , Hash router!!!







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

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

/**
* 當(dāng)頁面刷新的時(shí)候
*/
Router.prototype.refresh = function () {
/**
* 獲取當(dāng)前頁面中的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);
/**
* 將當(dāng)前hash路由推入數(shù)組儲(chǔ)存,指針向前移動(dòng)
*/
this.history.push(this.currentUrl);
this.currentIndex++;
}
this.isBack = false;
/**
* 執(zhí)行當(dāng)前hash路徑的回調(diào)函數(shù)
*/
this.routers[this.currentUrl]();
console.log("refresh");
console.log(this.history);
console.log(this.currentIndex);
};
/**
* 當(dāng)頁面后退,回退的過程中會(huì)觸發(fā)hashchange,將hash重新放入,索引增加
*/
Router.prototype.back = function () {
console.log("back");
console.log(this.history);
console.log(this.currentIndex);
// 后退操作設(shè)置為true
this.isBack = true;
/**
* 如果指針小于0的話就不存在對(duì)應(yīng)hash路由了,因此鎖定指針為0即可
*/
this.currentIndex <= 0
? (this.currentIndex = 0)
: (this.currentIndex = this.currentIndex - 1);
/**
* 隨著后退,location.hash也應(yīng)該隨之變化
* 并執(zhí)行指針目前指向hash路由對(duì)應(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來實(shí)現(xiàn)URL的變化,其中最主要用history.pushState()新增一個(gè)歷史記錄,用history.replaceState()直接替換當(dāng)前歷史記錄,可以在不進(jìn)行刷新的情況下,操作瀏覽器的歷史記錄。需要后臺(tái)配置支持,因?yàn)槲覀兊膽?yīng)用是個(gè)單頁的客戶端應(yīng)用,如果后臺(tái)沒有正確的配置,當(dāng)用戶在瀏覽器直接訪問一些沒有配置的路徑就會(huì)返回404,但因?yàn)闆]有#號(hào),所以當(dāng)用戶刷新頁面之類的操作時(shí),瀏覽器還是會(huì)給服務(wù)器發(fā)送請(qǐng)求。為了避免出現(xiàn)這種情況,所以這個(gè)實(shí)現(xiàn)需要服務(wù)器的支持,需要定向到根路徑。html5 提供了historyAPI來實(shí)現(xiàn)URL的變化,其中最主要的 API 有以下兩個(gè):

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






前端路由


hello , History router!!!







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

// history.js
/**
* history路由
*/
class Router {
constructor() {
/**
* 以鍵值對(duì)的形式存儲(chǔ)路由
*/
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以及對(duì)應(yīng)的callback函數(shù)儲(chǔ)存
* @param {*} path
* @param {*} callback
*/
Router.prototype.route = function (routes) {
for (let route of routes) {
this.routers[route.path] = route.callback || function () { };
}
};

/**
* 初始化,直接替換當(dāng)前歷史紀(jì)錄,并用狀態(tài)對(duì)象進(jìn)行存儲(chǔ)
*/
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);
};

/**
* 更新頁面,新增一個(gè)歷史紀(jì)錄
*/
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標(biāo)簽會(huì)跳轉(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é)

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

??想了解更多內(nèi)容,請(qǐng)?jiān)L問:??

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

??https://ost.??


文章名稱:前端路由與單頁頁面實(shí)踐
網(wǎng)頁URL:http://m.5511xx.com/article/dpoidhc.html