Merkmale einer Single-Page-Anwendung„Annahme:“ Auf einer Webseite gibt es eine Schaltfläche, über die man durch Anklicken zu anderen Seiten der Site springen kann. „Mehrseitige Anwendung“: Klicken Sie auf die Schaltfläche, um eine HTML-Ressource neu zu laden und die gesamte Seite zu aktualisieren. „Einzelseitenanwendung“: Wenn Sie auf eine Schaltfläche klicken, erfolgt keine neue HTML-Anforderung, sondern nur eine teilweise Aktualisierung. Dadurch kann ein nahezu natives und reibungsloses Erlebnis geschaffen werden. Warum können SPA-Single-Page-Anwendungen nahezu ohne Aktualisierung auskommen? Wegen seiner SP – Single-Page. Beim ersten Aufruf der Anwendung wird lediglich die HTML-Seite und deren öffentliche statische Ressourcen zurückgegeben. Die nachfolgenden sogenannten „Sprünge“ holen sich nicht mehr die HTML-Datei vom Server, sondern sind lediglich DOM-Ersetzungsoperationen, die simuliert werden. Wie erfasst js also den Zeitpunkt des Komponentenwechsels und ändert die Browser-URL ohne Aktualisierung? Verlassen Sie sich auf Hash und HTML5History. Hash-RoutingBesonderheit
Prinzip Hash HTML5History-Routing Besonderheit
Prinzip HTML5Geschichte Interpretation des Vue-Router-QuellcodesNehmen wir als Beispiel den Router vue-router von Vue und werfen wir einen Blick auf seinen Quellcode. Tipps: Da der Schwerpunkt dieses Artikels auf der Erläuterung der beiden Modi der Einzelseitenweiterleitung liegt, werden nachfolgend nur einige Schlüsselcodes aufgeführt, die hauptsächlich Folgendes erklären:
Plugin registrieren Zunächst müssen Sie als Plug-In bewusst eine Installationsmethode für die Verwendung durch Vue bereitstellen. In der Datei install.js des Quellcodes wird die Installationsmethode zum Registrieren und Installieren des Plug-Ins definiert, die Methode wird in die Hook-Funktion jeder Komponente eingemischt und die Route wird initialisiert, wenn der Hook beforeCreate ausgeführt wird: Vue.mixin({ vorErstellen () { wenn (isDef(this.$options.router)) { this._routerRoot = dies dieser._router = dieser.$options.router dies._router.init(dies) Vue.util.defineReactive(dies, '_route', dies._router.history.current) } anders { dies._routerRoot = (dieses.$parent && dies.$parent._routerRoot) || dies } registerInstance(dies, dies) }, // Im gesamten Text wird ... verwendet, um ausgelassene Methoden anzuzeigen ... }); Unterscheidungsmodus Dann finden wir die Basisklasse VueRouter des gesamten Plug-Ins aus index.js. Es ist nicht schwer zu erkennen, dass sie je nach Modus unterschiedliche Routing-Instanzen im Konstruktor verwendet. ... importiere {install} von './install'; importiere {HashHistory} aus './history/hash'; importiere {HTML5History} aus './history/html5'; ... exportiere Standardklasse VueRouter { statische Installation: () => void; Konstruktor (Optionen: RouterOptions = {}) { wenn (dieser.fallback) { Modus = "Hash" } wenn (!imBrowser) { Modus = "abstrakt" } this.mode = Modus Schalter (Modus) { Anamnese': diese.History = neue HTML5History(diese, Optionen.Basis) brechen Fall 'Hash': diese.History = neue HashHistory(diese, Optionen.Basis, diese.Fallback) brechen Fall 'abstrakt': diese.History = neue AbstractHistory(diese, options.base) brechen Standard: wenn (Prozess.Umgebung.NODE_ENV !== 'Produktion') { assert(false, `ungültiger Modus: ${mode}`) } } } } Registrieren Sie die Router-Link-Komponente global An dieser Stelle können wir fragen: Wo werden bei der Verwendung von Vue-Router die allgemeinen <router-link/> und <router-view/> eingeführt? Zurück zur Datei install.js. Sie importiert und registriert die Komponenten „Router-View“ und „Router-Link“ global: Importiere Ansicht aus „./components/view“. Link aus „./components/link“ importieren; ... Vue.component('RouterView', Ansicht); Vue.component('RouterLink', Link); In ./components/link.js ist das Klickereignis standardmäßig an die Komponente <router-link/> gebunden, und der Klick löst die Handlermethode aus, um den entsprechenden Routingvorgang auszuführen. const handler = e => { wenn (guardEvent(e)) { wenn (dies.ersetzen) { router.replace(Standort, noop) } anders { router.push(Standort, noop) } } }; Wie eingangs erwähnt, initialisiert der VueRouter-Konstruktor für unterschiedliche Modi unterschiedliche Modi von History-Instanzen, sodass auch die Methoden von router.replace und router.push unterschiedlich sind. Als Nächstes werden wir den Quellcode dieser beiden Modi herunterladen. Hash-Modus In der Datei history/hash.js ist die Klasse HashHistory definiert, die von der Basisklasse History in history/base.js erbt. Tatsächlich hatte ich einige Zweifel, als ich das zum ersten Mal las. Da es sich bereits im Hash-Modus befindet, warum müssen wir dann den Support von PushState beurteilen? Es stellt sich heraus, dass history.pushState zur Unterstützung von scrollBehavior einen Schlüsselparameter übergeben kann, sodass jeder URL-Verlauf einen Schlüssel hat und der Schlüssel zum Speichern der Standortinformationen jeder Route verwendet wird. Gleichzeitig ist die an den Prototyp gebundene Methode „setupListeners“ dafür verantwortlich, auf den Zeitpunkt von Hash-Änderungen zu achten: In Browserumgebungen, die den HTML5History-Modus unterstützen, achtet sie auf Popstate-Ereignisse, in anderen Browsern auf Hash-Änderungen. Nach der Überwachung der Änderungen wird die Methode handleRoutingEvent ausgelöst, die TransitionTo-Sprunglogik der übergeordneten Klasse aufgerufen und der DOM-Ersetzungsvorgang ausgeführt. importiere { pushState, replaceState, supportsPushState } von '../util/push-state' ... exportiere Klasse HashHistory erweitert History { setupListeners() { ... const handleRoutingEvent = () => { const current = dies.aktuell wenn (!ensureSlash()) { zurückkehren } // Die Sprungmethode unter der übergeordneten Klasse History wird von transitionTo aufgerufen. Der Pfad wird nach dem Sprung gehasht this.transitionTo(getHash(), route => { if (unterstütztScroll) { handleScroll(dieser.Router, Route, aktuell, wahr) } wenn (!supportsPushState) { replaceHash(route.vollständigerPfad) } }) } const eventType = unterstütztPushState ? 'popstate' : 'hashchange' Fenster.addEventListener( Ereignistyp, RoutingEvent-Handle ) dies.listeners.push(() => { window.removeEventListener(Ereignistyp, Routing-Ereignis behandeln) }) } push (Standort: Rohstandort, bei Abschluss?: Funktion, bei Abbruch?: Funktion) { const { current: fromRoute } = dies dies.transitionTo( Standort, Route => { pushHash(route.vollständigerPfad) handleScroll(dieser.Router, Route, vonRoute, false) beiAbgeschlossen und beiAbgeschlossen(Route) }, beiAbbruch ) } } ... // Den eingehenden Pfad in eine gehashte URL verarbeiten Funktion getUrl (Pfad) { const href = fenster.standort.href const i = href.indexOf('#') const base = i >= 0 ? href.slice(0, i) : href gibt `${base}#${path}` zurück } ... // Hash ersetzen Funktion pushHash (Pfad) { if (unterstütztPushState) { pushState(getUrl(Pfad)) } anders { window.location.hash = Pfad } } //Methode in der Datei util/push-state.js export const supportsPushState = imBrowser && (Funktion () { const ua = window.navigator.userAgent Wenn ( (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) && ua.indexOf('Mobile Safari') !== -1 && ua.indexOf('Chrome') === -1 && ua.indexOf('Windows Phone') === -1 ) { return false } gibt window.history und Typ von window.history.pushState zurück === 'Funktion' })() HTML5History-Modus Ebenso ist die Klasse HTML5History in history/html5.js definiert. Definieren Sie die Push-Prototypmethode und rufen Sie history.pusheState auf, um den Browserpfad zu ändern. Gleichzeitig überwacht die SetupListeners-Methode des Prototyps das Popstate-Ereignis und nimmt rechtzeitig DOM-Ersetzungen vor. importiere {pushState, replaceState, supportsPushState} aus '../util/push-state'; ... Exportklasse HTML5History erweitert History { setupListeners() { const handleRoutingEvent = () => { const aktuell = dies.aktuell; const location = getLocation(diese.base); wenn (dieser.aktuelle === START && Standort === dieser._startStandort) { zurückkehren } dies.transitionTo(Standort, Route => { if (unterstütztScroll) { handleScroll(Router, Route, aktuell, wahr) } }) } window.addEventListener('popstate', handleRoutingEvent) dies.listeners.push(() => { window.removeEventListener('popstate', handleRoutingEvent) }) } push (Standort: Rohstandort, bei Abschluss?: Funktion, bei Abbruch?: Funktion) { const { current: fromRoute } = dies dies.transitionTo(Standort, Route => { pushState(saubererPfad(diese.Basis + Route.vollständigerPfad)) handleScroll(dieser.Router, Route, vonRoute, false) beiAbgeschlossen und beiAbgeschlossen(Route) }, beiAbbruch) } } ... //Methode in util/push-state.js Dateiexportfunktion pushState (URL?: Zeichenfolge, Ersetzen?: Boolescher Wert) { saveScrollPosition() const history = fenster.history versuchen { wenn (ersetzen) { const stateCopy = erweitern({}, Verlauf.Zustand) stateCopy.key = getStateKey() history.replaceState(Staatskopie, '', URL) } anders { history.pushState({ Schlüssel: setStateKey(genStateKey()) }, '', URL) } } fangen (e) { window.location[ersetzen? 'ersetzen': 'zuweisen'](URL) } } transitionTo behandelt die Routenänderungslogik Die beiden oben genannten Routing-Modi lösen beide this.transitionTo beim Abhören aus. Was ist das? Es handelt sich eigentlich um eine Prototypmethode, die in der Basisklasse history/base.js definiert ist und zur Handhabung der Routing-Änderungslogik verwendet wird. Verwenden Sie zunächst const route = this.router.match(location, this.current), um den übergebenen Wert mit dem aktuellen Wert zu vergleichen und das entsprechende Routenobjekt zurückzugeben. Bestimmen Sie dann, ob die neue Route mit der aktuellen Route identisch ist. Wenn ja, geben Sie sie direkt zurück. Wenn nicht, führen Sie den Rückruf in this.confirmTransition aus, um das Routenobjekt zu aktualisieren und das ansichtsbezogene DOM zu ersetzen. Exportklasse Verlauf { ... Übergang zu ( Standort: RawLocation, onComplete?: Funktion, onAbort?: Funktion ) { const route = dieser.router.match(Standort, dieser.aktuell) dies.confirmTransition( Route, () => { const prev = dies.aktuell dies.updateRoute(route) beiAbgeschlossen und beiAbgeschlossen(Route) dies.ensureURL() dies.router.afterHooks.forEach(hook => { Hook und Hook (Route, vorherige) }) wenn (!diese.bereit) { dies.ready = true dies.readyCbs.forEach(cb => { cb(Route) }) } }, err => { if (beiAbbruch) { beiAbbruch(fehler) } wenn (err && !this.ready) { dies.bereit = wahr // https://github.com/vuejs/vue-router/issues/3225 wenn (!isRouterError(err, NavigationFailureType.redirected)) { dies.readyErrorCbs.forEach(cb => { cb(err) }) } anders { dies.readyCbs.forEach(cb => { cb(Route) }) } } } ) } ... } endlichNun, das Obige ist ein kleiner Einblick in das Routing einzelner Seiten. Ich hoffe, wir können es schaffen, von den ersten Schritten zu „niemals aufgeben“ zu kommen~~ Damit ist der Artikel abgeschlossen, in dem erklärt wird, wie man das Routing von Einzelseitenanwendungen im WeChat Mini-Programm in 10 Minuten gründlich versteht. Weitere relevante Inhalte zum Routing von Einzelseitenanwendungen im Mini-Programm finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: Grafisches Tutorial zur Installation der dekomprimierten Version von mysql5.7.14
>>: Mysql behält den vorhandenen Inhalt bei und fügt später Inhalte hinzu
Inhaltsverzeichnis Hintergrund Wirkung Ideen Hint...
Inhaltsverzeichnis Hintergrund analysieren Datens...
Inhaltsverzeichnis 1. Was ist ein Index? 2. Warum...
MySQL verfügt über die folgenden Protokolle: Fehl...
Dieser Artikel beschreibt die Installation des Sy...
In diesem Artikelbeispiel wird der spezifische Co...
<br />Dies ist eine Reihe von Tutorials, die...
Als ich heute nach einer Seite auf Baidu suchte, d...
Vorwort Dieses Steuerelement weist beim direkten ...
Verwenden Sie ein Profil, um langsames SQL zu ana...
Von der Entwicklung bis zur Bereitstellung: Mache...
serializable Serialisierung (kein Problem) Transa...
1. MySQL herunterladen 1. Melden Sie sich auf der...
Dieser Artikel erläutert anhand von Beispielen di...
Betriebssystem: Alibaba Cloud ESC-Instanz centos7...