Dieser Artikel stellt Ihnen eine detaillierte Analyse der Kernhistorienbibliothek in React Router vor. Ich hoffe, dass er für Freunde hilfreich ist.
React Router ist fast die einzige Wahl für die Routing-Verwaltung, um etwas komplexere Anwendungen zu entwickeln. Obwohl React Router vier große Versionsaktualisierungen durchlaufen hat und seine Funktionen immer umfangreicher geworden sind, hat sich seine Kernabhängigkeit von der Verlaufsbibliothek nicht geändert, egal wie er sich ändert. Werfen wir einen Blick darauf, welche Funktionen diese Bibliothek mit 4k+ Sternen auf Github bietet.
Apropos Geschichtsbibliothek: Denken Sie, dass Ihnen dieses Wort ein wenig bekannt vorkommt? Ja, der HTML5-Spezifikation wurde auch ein neues Verlaufsobjekt mit demselben Namen hinzugefügt. Werfen wir einen Blick darauf, welche Probleme mit diesem Verlaufsobjekt gelöst werden.
In der Zeit, als jQuery das Front-End dominierte, war das Anfordern von Seitenaktualisierungen über Ajax zu dieser Zeit eine sehr beliebte Methode zur Seitenverarbeitung. Zu dieser Zeit entwickelte sich der Prototyp von SPA. Um Änderungen an der Seite zu kennzeichnen, sodass nach dem Aktualisieren weiterhin die richtigen Seitenelemente angezeigt werden können, wird in der Regel der Hashwert der URL geändert, um die Seite eindeutig zu lokalisieren. Dies bringt jedoch ein weiteres Problem mit sich: Benutzer können die Seiten nicht vorwärts/rückwärts wechseln.
Um dieses Problem zu lösen, wurde das History-Objekt ins Leben gerufen. Wenn sich die URL oder der Hash der Seite ändert, überträgt der Browser automatisch die neue URL in das Verlaufsobjekt. Im Verlaufsobjekt wird ein Statusarray verwaltet, um Änderungen in der URL aufzuzeichnen. Wenn der Browser Vorwärts-/Rückwärtsvorgänge ausführt, ruft er tatsächlich die entsprechende Methode des Verlaufsobjekts (forward
/back
) auf, um den entsprechenden Status zum Seitenwechsel abzurufen.
Zusätzlich zur Bedienung der URL bietet das Verlaufsobjekt auch zwei Methoden, mit denen der interne Status aktualisiert werden kann, ohne die URL zu bedienen, nämlich pushState
und replaceState
. Sie können auch zusätzliche Daten im Status speichern und diese dann über onpopstate
im Ereignis event.state
abrufen. Wenn Sie ein tieferes Verständnis des Verlaufsobjekts wünschen, können Sie hier und hier nachschlagen.
Lassen Sie uns zurückgehen und einen Blick auf die Verlaufsbibliothek werfen. Es führt im Wesentlichen die folgenden vier Dinge aus:
Lernen aus dem Konzept des HTML5-Verlaufsobjekts und Erweitern einiger darauf basierender Funktionen
Bietet 3 Arten von Verlauf: BrowserHistory, HashHistory, MemoryHistory und verwaltet eine einheitliche API
Unterstützt die Publish/Subscribe-Funktion. Wenn sich der Verlauf ändert, kann die Abonnementfunktion automatisch ausgelöst werden
Bietet praktische Funktionen wie Sprungabfangen, Sprungbestätigung und Basisname
Vergleichen Sie einige Ähnlichkeiten und Unterschiede zwischen den beiden APIs. Das Folgende ist die Verlaufsbibliothek:
const history = { length, // 属性,history中记录的state的数量 action, // 属性,当前导航的action类型 location, // 属性,location对象,封装了pathname、search和hash等属性 push, // 方法,导航到新的路由,并记录在history中 replace, // 方法,替换掉当前记录在history中的路由信息 go, // 方法,前进或后退n个记录 goBack, // 方法,后退 goForward, // 方法,前进 canGo, // 方法,是否能前进或后退n个记录 block, // 方法,跳转前让用户确定是否要跳转 listen // 方法,订阅history变更事件 };
Das Folgende ist das HTML5-Verlaufsobjekt:
const history = { length, // 属性,history中记录的state的数量 state, // 属性,pushState和replaceState时传入的对象 back, // 方法,后退 forward, // 方法,前进 go, // 方法,前进或后退n个记录 pushState, // 方法,导航到新的路由,并记录在history中 replaceState // 方法,替换掉当前记录在history中的路由信息 } // 订阅history变更事件 window.onpopstate = function (event) { ... }
Aus dem Vergleich ist ersichtlich, dass die Beziehung zwischen den beiden sehr eng ist Man kann sagen, dass es sich um das Verlaufsobjekt handelt. Eine Obermenge von , bei der es sich um ein leistungsfähigeres Verlaufsobjekt handelt.
Im Folgenden nehmen wir einen der drei Verlaufstypen, hashHistory, als Beispiel, um den Verlaufsquellcode zu analysieren und zu sehen, was er bewirkt. Schauen wir uns zunächst an, wie es mit Hash-Änderungen umgeht.
// 构造hashHistory对象 const createHashHistory = (props = {}) => { ... const globalHistory = window.history; // 引用HTML5 history对象 ... // transitionManager负责控制是否进行跳转,以及跳转后要通知到的订阅者,后面会详细讨论 const transitionManager = createTransitionManager(); ... // 注册history变更回调的订阅者 const listen = listener => { const unlisten = transitionManager.appendListener(listener); checkDOMListeners(1); return () => { checkDOMListeners(-1); unlisten(); }; }; // 监听hashchange事件 const checkDOMListeners = delta => { listenerCount += delta; if (listenerCount === 1) { window.addEventListener(HashChangeEvent, handleHashChange); } else if (listenerCount === 0) { window.removeEventListener(HashChangeEvent, handleHashChange); } }; // hashchange事件回调 const handleHashChange = () => { ... // 构造内部使用的location对象,包含pathname、search和hash等属性 const location = getDOMLocation(); ... handlePop(location); }; // 处理hash变更逻辑 const handlePop = location => { ... const action = "POP"; // 给用户展示确认跳转的信息(如果有的话),确认后通知订阅者。如果用户取消跳转,则回退到之前状态 transitionManager.confirmTransitionTo(location, action, getUserConfirmation, ok => { if (ok) { setState({action, location}); // 确认后通知订阅者 } else { revertPop(location); // 取消则回退到之前状态 } }); }; // 更新action,location和length属性,并通知订阅者 const setState = nextState => { Object.assign(history, nextState); history.length = globalHistory.length; transitionManager.notifyListeners(history.location, history.action); }; ... }
Das Obige ist die Logik für den Umgang mit passiven Hash-Änderungen. In einem Satz kann sie wie folgt zusammengefasst werden: Abonnieren Sie das Hash-Änderungsereignis, stellen Sie fest, ob die Änderung wirklich erforderlich ist, und aktualisieren Sie Ihre eigenen Attribute, wenn a Wenn eine Änderung erforderlich ist, benachrichtigen Sie den Abonnenten. Wenn keine Änderung erforderlich ist, kehren Sie zum vorherigen Status zurück.
Schauen wir uns an, was der TransitionManager tut. Konzentrieren Sie sich auf den Inhalt im Zusammenhang mit dem Veröffentlichen/Abonnieren und ignorieren Sie den Inhalt im Zusammenhang mit dem Benutzerbestätigungssprung.
const createTransitionManager = () => { ... // 内部维护的订阅者列表 let listeners = []; // 注册订阅者 const appendListener = fn => { let isActive = true; const listener = (...args) => { if (isActive) fn(...args); }; listeners.push(listener); return () => { isActive = false; listeners = listeners.filter(item => item !== listener); }; }; //通知订阅者 const notifyListeners = (...args) => { listeners.forEach(listener => listener(...args)); }; ... }
Der Code hier ist auf den ersten Blick klar. Er dient dazu, eine Abonnentenliste zu verwalten und die relevanten Funktionen zu benachrichtigen, wenn sich der Hash ändert.
Das Obige ist der Inhalt, der sich auf die passive Aktualisierung bezieht, wenn sich der Hash ändert. Am Beispiel von push
ist der Code ähnlich. replace
const push = (path, state) => { ... const action = "PUSH"; const location = createLocation(path, undefined, undefined, history.location); transitionManager.confirmTransitionTo(location, action, getUserConfirmation, ok => { if (!ok) // 如果取消,则不跳转 return; ... pushHashPath(encodedPath); // 用新的hash替换到url当中 ... setState({action, location}); // 更新action,location和length属性,并通知订阅者 }); }; // 用新的hash替换到url当中 const pushHashPath = path => (window.location.hash = path);
const globalHistory = window.history; const go = n => { ... globalHistory.go(n); }; const goBack = () => go(-1); const goForward = () => go(1);
aufgerufen wird, ändert sich der Hash, was das Hashchange-Ereignis auslöst, und dann benachrichtigt die Verlaufsbibliothek die relevanten Abonnenten über die Änderung. window.history.go
Verwandte Empfehlungen:
Wie man h5 verwendet, um reagierende Drag-and-Drop-Sortierkomponenten (mit Code) zu implementieren
Wie HTML5 das Kollapsproblem von löst margin-top (Code beigefügt)
Was sind die Tags und allgemeinen Regeln in HTML5? Einführung in HTML5-Tags und -Regeln
Das obige ist der detaillierte Inhalt vonDetaillierte Analyse der Kernhistorienbibliothek in React Router. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!