Qu'est-ce que le routage frontal
Le soi-disant routage frontal a la capacité que le navigateur client peut afficher différentes pages d'affichage en fonction de différentes URL sans dépendre du serveur.
La rationalité de l'existence du routage frontal
Quand l'épée d'Ajax n'a pas encore été révélée et que le front-end est encore à ses balbutiements, le routage Le travail est confié au backend. Lors du changement de page, le navigateur envoie différentes requêtes <code><span style="font-size: 14px;">url</span>
url ; lorsque le serveur reçoit la requête du navigateur, il analyse les différentes <code><span style="font-size: 14px;">url</span> <code><span style="font-size: 14px;">url</span><span style="font-size: 14px;">html</span>
pour épisser le html
ou le modèle requis, puis renvoyer le résultat au rendu du navigateur sur le côté serveur.
Le routage côté serveur est également non conventionnel et présente des avantages et des inconvénients. Son avantage est une sécurité accrue et un contrôle plus strict de l’affichage des pages. Ceci est utile dans certains scénarios, comme un processus de paiement de commande, où chaque étape ne peut être atteinte qu'après que l'étape précédente a été exécutée avec succès. Cela peut ajouter un mécanisme de vérification à chaque étape du processus côté serveur, et seule la page correcte sera renvoyée si la vérification est réussie. Le routage frontal ne peut donc pas mettre en œuvre la vérification à chaque étape ? Bien sûr que non, je crois que votre code peut être écrit de manière très rigoureuse pour garantir que le processus ne se déroulera pas mal dans des circonstances normales, mais un autre fait auquel il faut faire face est le suivant : le front-end n'a aucune sécurité. Les utilisateurs peuvent modifier le code à volonté pour entrer dans différents processus, et vous pouvez ajouter de nombreuses logiques de traitement pour cela. En comparaison, bien entendu, les droits d’accès à la page de contrôle back-end sont plus sûrs et plus simples. <span style="font-size: 14px;">reload</span>
En revanche, le routage back-end augmente sans aucun doute la charge côté serveur et nécessite un
page, L'expérience utilisateur n'est en fait pas bonne.
De cette façon, le routage front-end entre en jeu. Tout d’abord, son émergence réduit sans aucun doute la pression côté serveur. Surtout pour une application plus complexe, ou pour être plus précis, pour une application avec un système de routage complexe, le serveur doit exécuter un élément de logique de traitement pour chaque URL différente, ce qui est un peu insupportable dans des situations de forte concurrence. Il n'est pas nécessaire d'actualiser la page entière lors du changement de page. Il n'y a pas de retard réseau ni d'actualisation scintillante, ce qui améliore l'expérience utilisateur.
Méthode de mise en œuvre du routage front-end
- Maintenant que l'objectif est atteint, quels sont les problèmes que nous devons résoudre ? On peut décomposer un peu le problème, faire d'abord un petit plan de 100 millions, puis passer à l'étape suivante après l'avoir réalisé :)
<code><span style="font-size: 14px;">url</span> En partant du principe que la page ne s'actualise pas Implémenter
url -
change<code><span style="font-size: 14px;">url</span>
capture
afin d'effectuer une logique de remplacement de page<code><span style="font-size: 14px;">url</span>
Comment mettre en œuvre mise à joururl<code><span style="font-size: 14px;">url</span>et la page ne s'actualise pas
Comme mentionné précédemment, l'une des caractéristiques du front- le routage final par rapport au routage back-end est que la page n'est pas complètement actualisée. Changez la vue dans les circonstances. La page <code><span style="font-size: 14px;">value</span>
url a changé, mais elle n'a pas été rechargée ! Cela peut paraître un peu bizarre, mais ce n’est en réalité pas grave. <code><span style="font-size: 14px;">url</span>
valeur
de la zone de saisie. Mais ne déclenchez pas l'opération de requête de la page, afin que la nouvelle page ne soit pas rechargée. Si changer la valeur de la zone de saisie et envoyer la requête était une opération atomique, nous serions impuissants. Heureusement, la demande ne sera envoyée que lorsque nous appuierons sur Entrée (c'est évident). Par conséquent, cela crée des conditions nous permettant de modifier la valeur de la barre d’adresse sans déclencher une demande de rafraîchissement de la page. BOM fournit-il une méthode pour modifier la barre d'adresse du navigateur url
sans déclencher une opération de requête ? Ici, il existe deux manières de répondre aux besoins. La première consiste à utiliser le champ <code><span style="font-size: 14px;">url</span>
hash dans <span style="font-size: 14px;">hash</span>
<code><span style="font-size: 14px;">url</span> ; la deuxième consiste à utiliser l'API d'historique
<span style="font-size: 14px;">hash</span>
hash
Façon<span style="font-size: 14px;">http</span>
Comprendre<code><span style="font-size: 14px;">url</span>
http Le protocole saura que <span style="font-size: 14px;">#</span>
<code><span style="font-size: 14px;">url</span>
<span style="font-size: 14px;">#</span>
<span style="font-size: 14px;">http://www.gmail.com/text/#123</span>
. <span style="font-size: 14px;">123</span>
Par exemple : <code><span style="font-size: 14px;">url</span>
http://www.gmail.com/text/#123, <span style="font-size: 14px;">hash</span>
<span style="font-size: 14px;">123</span>
<code>url<code><span style="font-size: 14px;">location.hash</span>
>hash<code><span style="font-size: 14px;">url</span> partie. <span style="font-size: 14px;">hash</span>
Ouvrez la console et entrez <code><span style="font-size: 14px;">url</span>
location.hash, vous pouvez obtenir le <span style="font-size: 14px;">hash</span>
La partie <span style="font-size: 14px;"><code>
hash<span style="font-size: 14px;">location.hash = '123'</span>
de l'url<code><span style="font-size: 14px;">url</span> (si le url<code><span style="font-size: 14px;">#123</span>
n'existe pas
renvoie une chaîne vide). Ensuite, entrez
location.hash = '123', et vous trouverez <code><span style="font-size: 14px;">history</span>
url a changé, et le champ <code><span style="font-size: 14px;">window.history</span>
#123 a été ajouté à la fin, et la page n'a pas été actualisée . Évidemment, cela répond à nos exigences.
API d'historique<span style="font-size: 14px;">pushState</span>
<span style="font-size: 14px;">replaceState</span>
HTML5 introduit un historique
<span style="font-size: 14px;">history.replaceState(dataObj, title, url);<br/>history.pushState(dataObj, title, url);<br/></span>L'API L'objet contient un ensemble d'API pour accéder à l'historique du navigateur, accessible via
<code><span style="font-size: 14px;">window.history</span><code><span style="font-size: 14px;">url</span>. <code><span style="font-size: 14px;">url</span>On s'intéresse ici à ses deux méthodes API :
dans la barre d'adresse du navigateur avec l'et
remplaceState
<span style="font-size: 14px;">pushState</span>
. <code><span style="font-size: 14px;">url</span><span style="font-size: 14px;">replaceState</span>
Comme indiqué ci-dessus, ils reçoivent exactement les mêmes paramètres, tous deux fonctionnent sur la pile d'historique du navigateur, poussent l'URL transmise et les données associées sur la pile et remplacent leurl
<code><span style="font-size: 14px;">url</span>
et sans actualiser le page (juste ce qu'il faut !).
<code><span style="font-size: 14px;">url</span>Au fait, la différence est que
pushStatespécifiera le <code><span style="font-size: 14px;">url</span>url est placé directement en haut de la pile d'historique, tandis que
replaceState
doit remplacer l'enregistrement d'historique actuel Le haut de la pile est remplacé par les données entrantes. Les deux méthodes peuvent nous aider à remplir les conditions de définition des questions. En plus des préférences subjectives, la méthode à adopter doit également être basée sur des faits objectifs : les navigateurs de versions inférieures ont une mauvaise compatibilité avec l'API d'historique. Par exemple, lorsqu'on rencontre IE8, il ne semble pas y avoir de choix. Comment suivre les url
modifications dans le navigateur Côté client, les mécanismes de surveillance des événements sont généralement utilisés pour suivre les modifications des attributs du formulaire, et le suivi des modifications dans url
n'est pas non plus conventionnel. 对于<span style="font-size: 14px;">hash</span>
方式的前端路由,通常可以监听 <span style="font-size: 14px;">hashchange</span>
事件,在事件回调中处理相应的页面视图展示等逻辑。
此外,HTML5提供的 <span style="font-size: 14px;">popstate</span>
事件也会在<code><span style="font-size: 14px;">url</span>的<span style="font-size: 14px;">hash</span>
发生改变时触发。也就是说如果可以忽略低版本浏览器,我们使用<span style="font-size: 14px;">hash</span>
方式路由时也可以采用监听这个事件进行回调处理。
那么,如果是采用history API的形式呢?根据MDN的描述:
调用
<span style="font-size: 14px;">history.pushState()</span>
或者<span style="font-size: 14px;">history.replaceState()</span>
不会触发<span style="font-size: 14px;">popstate</span>
事件。<span style="font-size: 14px;">popstate</span>
事件只会在浏览器某些行为下触发, 比如点击后退按钮(或者在JavaScript中调用<span style="font-size: 14px;">history.back()</span>
方法)。
这也就是说,我们在使用history API改变浏览器的<code><span style="font-size: 14px;">url</span>时,仍需要额外的步骤去触发 <span style="font-size: 14px;">popstate</span>
事件,例如调用 <span style="font-size: 14px;">history.back()</span>
会 <span style="font-size: 14px;">history.forward()</span>
等方法。
从兼容性上来讲,前面有提及<span style="font-size: 14px;">hash</span>
的方式兼容性更好。然而,对于低版本的浏览器,例如IE6等等,不支持 <span style="font-size: 14px;">hashchange</span>
事件。这个时候我们只能通过 <span style="font-size: 14px;">setInterval</span>
设置心跳的方式去模拟 <span style="font-size: 14px;">hashchange</span>
。
<span style="font-size: 14px;">var oldHash = location.hash;var oldURL = location.href;<br/><br/>setInterval(function() { var newHash = location.hash; var newURL = location.href; if (newHash !== oldHash && typeof window.onhashchange === 'function') { // 执行onhashchange回调<br/> window.onhashchange({ 'type': 'hashchange', 'oldURL': oldURL, 'newURL': newURL<br/> });<br/><br/> oldHash = newHash;<br/> oldURL = newURL;<br/> }<br/>}, 100);<br/></span>
一个简单实现
这里,给出一个很简单的实现:
<span style="font-size: 14px;">router.js</span>
<span style="font-size: 14px;">function FrontRouter() { this.routes = {};<br/> window.addEventListener('load', this.resolve.bind(this), false);<br/> window.addEventListener('hashchange', this.resolve.bind(this), false);<br/>}<br/><br/>FrontRouter.prototype.route = function(path, callback) { this.routes[path] = callback || function() {};<br/>};<br/><br/>FrontRouter.prototype.resolve = function() { this.curHash = location.hash.slice(1) || '/'; typeof this.routes[this.curHash] === 'function' && this.routes[this.curHash]();<br/>};<br/></span>
<span style="font-size: 14px;">index.html</span>
<span style="font-size: 14px;"><ul> <li><a href='#blue'></a></li> <li><a href='#yellow'></a></li> <li><a href='#red'></a></li></ul><br/></span>
<span style="font-size: 14px;">index.js</span>
<span style="font-size: 14px;">var router = new FrontRouter();<br/><br/>router.route('blue', function() {<br/> document.body.style.backgroundColor = 'blue';<br/>});<br/><br/>router.route('yellow', function() {<br/> document.body.style.backgroundColor = 'yellow';<br/>});<br/><br/>router.route('red', function() {<br/> document.body.style.backgroundColor = 'red';<br/>});<br/></span>
一点总结
应用场景
前端路由大部分的应用场景,就是我们现在熟知的单页应用SPA。
不存在纯前端路由
我们此前所描述的前端路由,建立在已经打开了一个初始页面基础之上,然后在这个页面之内进行页面替换。然而,我们如何进入这个初始页面?仅靠前端路由肯定是力所不及。我们至少要向后端发送一次http请求,接收所需要加载的页面不是吗?
所以,我们并不能抛弃后端路由部分。这也意味着,我们需要和后端确认各自的分工,哪些url归前端解析,哪些归后台解析。