navigation
[Deep 01] Execution context [Deep 02] Prototype chain [Deep 03] Inheritance [Deep 04] Event loop [Deep 05] Curri Bias function [Deep 06] Function memory [Deep 07] Implicit conversions and operators [Deep 07] Browser caching mechanism (HTTP caching mechanism) [Deep 08] Front-end security [Deep 09] Deep copy [Deep 10] Debounce Throttle [Deep 10] Front-end routing [Deep 12] Front-end modularization [Deep 13] Observer mode Publish subscribe mode Bidirectional data binding [Deep 14] Canvas [Deep 15] webSocket Webpack HTTP and HTTPS CSS- Interview Handwriting Promise
[react] Hooks
[Deployment 01] Nginx [Deployment 02] Docker deployVue project [Deployment 03] gitlab-CI
[source code – Webpack01 – precompiler] AST abstract syntax tree [source code – Webpack02 – Precompiler] Tapable [source code – Webpack03] hand written webpack-compiler simple compilation process [source code] Redux React-redux01 [source] Axios [source] vuex [source -vue01] Data responsive and initialized rendering [source -vue02] Computed responsive – Initialization, access, update process
Front knowledge
The URL and URI
- URI: Uniform resource Identifier (I => Identifier: Identifier Id)
(Universal Resource Identifier
- URL: uniform resource Locator (L => Locator: Locator)
Uniform Resource Locator
- The difference between:
- URL: The emphasis is on the address, that is (location) this unique resource
- URI: The emphasis is on (identifying) the resource, the uniqueness of the resource
It is difficult to identify a unique resource and a unique address separately, so the URL also acts as a RUI, marking a unique resource as well as the unique address of that resource
The composition of the URL
http://www.baidu.com:80/stu/index.html?name=xxx&age=25#teacher
- Protocol: the agreement
http://
,https://
- Domain: the Domain name
www.baicu.com
- Port: the Port
: 80
- The default HTTP address is 80
- The default address for HTTPS itself is 443
- Path: file Path, =>
/ start? The previous part
, in this case:/stu/index.html
- Query: Query string =>
? Beginning to end, or? It starts before #
, in this example:? name=xxx&age=25
- Hash: Hash =>
# Beginning to End
, in this example:teacher
- Protocol, Domain, Port, Path, Query, hash
DOMContentLoaded event, load event
- window.onload
window.addEventListener('load', ....)
- DOMContentLoaded
- The difference between:
- DOMContentLoaded: Triggered when the DOM is loaded
- Load: Triggers only when all resources, such as DOM, styles, scripts, images, and videos, have been loaded
DOM complete parsing process: 1. Parse HTML 2. Parse CSS - including styles in HTML and imported styles 3. Parsing and run the script - an error in this HTML script and external script 4. The introduction of the DOM to build complete -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- DOM loading is completed, Trigger DOMContentLoaded 5. Loading pictures, video, and other resources 6. Page load to complete -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- page loading is completed, Trigger load -- // 2021/07/25 update -- the above procedure is not perfect, Here again simple record / / - 1. See https://juejin.cn/post/6983570939342487565 parse HTML - 2. Parse - styleSheet (3) the evaluate - script 4. layout 5. paint 6. compositeCopy the code
A special case of string slice method
- Slice can be used for (arrays) and (strings)
- Returns a value without changing the string
- String.prototype.slice(start position, end position) Cuts a String, excluding the end position
String.prototype.slice() special case: ''.slice(1) ----------- returns '' empty String case: window.location.hash // because: When there is no address bar of the hash in the url, window. The location. The hash returns an empty string, this kind of situation / / so as follows: the window. The location. The hash. Slice (1) = > returns an empty stringCopy the code
Window. The location object
Window. location object property: pathName: Return the PATH part of the URL, / start? If no query and hash origin: protocal + hostname + port are used, the value is equal to the protocol, domain name, and port. Host name port: indicates the port number. Host: indicates the host (hostname + port). Start before #, or? Hash: Fragment string (hash value, # beginning to end) -window. location returns a read-only location object, you can still assign it a DOMString - this means you can handle location most of the time, Just as if it were a string - window.location = 'http://www.example.com', is a synonym for window.location.href = 'http://www.example.com' : - The difference between window.location.assign() and window.location.href? - Location.assign (URL) is a functional way - window.location.href= URL is faster than location.assign(URL)Copy the code
Hash routing
- The hash in the URL begins with a # and is originally used as an anchor point to navigate to a specific area of the page
- When the hash changes, the page does not refresh and the browser does not send a request to the server
- Note: When the hash changes, a HashChange event can be triggered, and data can be requested in the listening function to update the page
Serve as anchor points to locate page feature areas
<a href="#anchor1"> </a> <a href="#anchor2"> </a> <div id="anchor1"> </div> <div ID ="anchor2"> </div> - Click A2 and the page will jump to the location of Div2 - and the hash part of the page will change, that is, the string starting with # in the URL will change - Note: The name attribute of the a tag has been deprecated and replaced with an ID (because some tutorial uses the name attribute)Copy the code
Hashchange events
- If the hashChange event is listened for and the hash changes, the hash part of the URL in the address bar changes and hashChange is triggered
- But the page does not refresh, that is, the circle of the browser’s refresh button does not rotate
- But you can use hashChange’s callback function to update the contents of the page, not to refresh the page
<a href="#anchor2"> anchor2 </a> <script> window.addeventlistener ('hashchange', Function () {console.log('111111111')}, false) < script> </body> - Click the a tag, the HASH in the URL changes, the hash changes, the hashChange event fires, the listening function executes, output 111111Copy the code
Manually implement a hash-router
The hashChange event is triggered. (2) The view code is updated in the callback function of the HashChange event: <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Word-wrap: break-word! Important; "> <meta http-equiv=" x-uA-compatible "content="ie=edge"> <title>Document</title> <body> <a Href ="#/home">home</a> <a href="#/other">other</a> <div id="content"> </div> <script> const routes = [{path: '/ home' component: '< h1 > home page < / h1 >'}, {path: '/ other, component: '<h1>other page </h1>'}] class route {constructor(routes) {this.route = {} this.createroutemap (routes) } createRouteMap = (routes) => {routes. ForEach (item => {this.route[item.path] = () => {this.route[item.path] = () => { Document.getelementbyid ('content').innerHTML = item.componentdocument.getelementById ('content').innerHTML = item.componentDocument.getelementById ('content') } (componet (componet)} (componet (componet)); })} init = () => {window.addeventListener ('load', this.updateView, false) DOMContentLoaded window.addeventListener (' hashChange ', this.updateView, false) } updateView = () => { const hash = window.location.hash.slice(1) || '/home'; // When the load event is triggered, Window.location.hash => return 'empty string' // '.slice(1) => return 'if (this.route[hash]) this.route[hash]() exists, }} new Router(routes) </script> </body> </ HTML >Copy the code
2020/12/24 Review – Hash routing
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Word-wrap: break-word! Important; "> < span style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 13px! Important; white-space: normal;" < span style =" box-sizing: border-box; color: RGB (0, 0, 0); line-height: 22px; font-size: 13px! Important; word-break: inherit! Important;" '/home', component: 'home page contents'}, {path: '/other', component: }] class HashRouter {constructor(routes) {this.route = {} // route map this.createroutemap (routes) Create (map) mapping for (this.route); key=path; Value =()=>{update page} this.init()} createRouteMap =(routes) =>{if (routes. Length) {routes. }) => {document.getelementById ('content').innerhtml = component}})}} createRouteMap = (routes) => { if (routes.length) { routes.forEach(({ path, }) => {document.getelementById ('content').innerhtml = component}})}} init = () => { window.addEventListener('load', this.updateView, false) window.addEventListener('hashchange', this.updateView, False)} // updateView = () => {// (1) // Both (load event) and (hashChange event) are generated (updateView method) // The DOMContentLoaded event is triggered when the page has finished loading. // (3) // The hash is not changed when the load event is fired, Window.location.hash = '=> '.slice(1) =>' const hash = this.getCurrenthash ( // this. Route [hash]() //} if (this. Route [hash]) This.route [hash]() // If the key pair in the this.route object exists, } / / will perform the function gets the current address bar hash getCurrentHash = () = > {const hash = window. The location. The hash. Slice (1) enclosing printHahToHtml (hash) // The return hash function is used to display the current hash in HTML. hash : When the '/home' // load event is triggered, the hash does not exist, hash='', in which case the default is to return the '/home' route // Window.location. hash => return 'empty string' // '.slice(1) => return '} printHahToHtml = (hash) => {const DOM = Document.getelementbyid ('current-hash') dom.innerhtml = 'The hash of the current page is :=> #${hash}' dom.style.setProperty ('background', 'yellow') DOM.style.setProperty('padding', '10px') } } new HashRouter(routes) </script> </body> </html>Copy the code
2021/07/25 Optimization – Hash routing
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, Initial scale = 1.0 "/ > < title > Document < / title > < / head > < body > < a href =" # / home "> home page < / a > < a href =" # / other "> other page < / a > < span style =" box-sizing: border-box; color: RGB (0, 0, 0); line-height: 22px; font-size: 13px! Important; word-break: inherit! Important;" "/home", component: "home page ",}, {path: "/other", component: "other page ",},]; class HashRouter { constructor(routes) { this.route = {}; this.createRouteMap(routes); this.init(); } init = () => { window.addEventListener("load", this.updateView, false); window.addEventListener("hashchange", this.updateView, false); this.DOM_CURRENT_HASH = document.getElementById("current-hash"); this.DOM_CONTENT = document.getElementById("content"); }; // createRouteMap = (routes) => { // if (routes.length) { // routes.forEach(({ path, component }) => { // this.route[path] = () => { // document.getElementById("content").innerHTML = component; // Replace content //}; / /}); / / / /}}; createRouteMap = (routes = []) => { routes.forEach( ({ path, component }) => (this.route[path] = () => (this.DOM_CONTENT.innerHTML = component)) ); }; // updateView = () => { // const hash = this.getCurrentHash(); // If (this.route[hash]) this.route[hash](); // Execute this function if the key pairs in the this.route object exist. //}; updateView = () => { const path = this.getCurrentHash(); this.route? .[path]? . (); }; // getCurrentHash = () => { // const hash = window.location.hash.slice(1); // this.printHahToHtml(hash); // This function is used to display the current hash in HTML. hash : "/home"; / /}; getCurrentHash = () => { const path = window.location.hash.slice(1) || "/home"; this.printHahToHtml(path); // This function is used to display the return path of the current hash in HTML; }; // printHahToHtml = (hash) => { // const DOM = document.getElementById("current-hash"); // dom.innerhtml = 'The hash of the current page is :=> #${hash}'; // DOM.style.setProperty("background", "yellow"); // DOM.style.setProperty("padding", "10px"); / /}; printHahToHtml = (hash) => { const DOM = this.DOM_CURRENT_HASH; Dom. innerHTML = 'The current page hash is :=> #${hash}'; DOM.style.setProperty("padding", "10px"); DOM.style.setProperty("background", "yellow"); }; } new HashRouter(routes); </script> </body> </html>Copy the code
The history of routing
Window. The history object
- Methods on the window.history object:
back()
.forward()
.go()
.pushState()
.replaceState()
- pushState()
- replaceState()
- PushState () and replaceState ()
- Does not trigger a page refresh, only changes to the History object and changes to the URL in the address bar
- Will change the URL, will not trigger the popState event, the URL in the address bar will change
window.history.pushState(state, title, url)
- window.history.pushState(state, title, url)
- State: An object associated with the added record
- Title: The title of the new page. All browsers now ignore this parameter and can pass an empty string
- Url: The new URL address, which must be in the same field as the current page, is displayed in the browser’s address bar
window.history.pushState({}, null, url)
- Note: pushState does not refresh the page, only changes the History object and the url in the address bar
- State objects can be read from history.state
popstate
- Conditions for triggering popState
- Browser forward and back buttons
- History.go (), history.back(), history.forward()
- Note: Windows. History. PushState (), and the window. The history, replaceState () will not trigger the popstate event
- Note: pushState() and replaceState() can change the URL, and do not send requests to the server, there is no #, better than hash routing, but the History route needs to be supported by the server, and all routes need to be redirected to the root page
Manually implement a history-router
The principle of analysis
- The first step: Attach a click event to each a tag. When the click event is triggered, the pushState() event is triggered to change the path part of the URL to the value of a’s data-href custom property, which is the path of the route. Pass window.history.pushState({}, null, path) to change the URL of the address bar
- Step 2: After changing the URL in the address bar, get the path part of the updated URL through window.location. pathName
- Step 3: Match the path with the key in the Route object, and then execute the function that updates the view
- Step 4:
This is just a line: step 1-3 is the case of clicking on the A TAB
There is another line: browser forward and backward, and functional navigation go() back() forward() is handled by popstate events, the process is similar
The history, principle of the router: (1) Encapsulate a method called after pushState() and replaceState() change the URL, and get the latest window.location.path in that method, More believe page (2) trigger popstate event code via go() back() forward() browser forward back and so on: <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Word-wrap: break-word! Important; "> <meta http-equiv=" x-uA-compatible "content="ie=edge"> <title>Document</title> <body> <a <a href="javascript:void(0)" data-href="/home">home</a> // HTML <a href="javascript:void(0)" < span style =" box-sizing: border-box; color: RGB (0, 0, 0); line-height: 20px; font-size: 13px! Important; word-break: inherit! Important;" '< h1 > home page < / h1 >'}, {path: '/ other, component: '<h1>other page </h1>'}] class constructor {constructor(routes) {this.route = {} This.createroutemap (routes) // Create a route map this.bindevent () // bind a tag click event this.init() // bind load and popState events} createRouteMap = (routes) => { routes.forEach(item => { this.route[item.path] = () => { document.getElementById('content').innerHTML = item.component } }) } bindEvent = () => { const a = Document. GetElementsByTagName (' a ') Array. The prototype. The forEach. Call (a, item = > {/ / the second argument, Is the callback function that forEach needs to pass in item.addeventListener ('click', () => {const path = item.getAttribute('data-href') // Get the data-herf attribute this.pushStateFn(path) // Execute the history.pushState () method // This refers to the context of the parent, which is the context of the bindEvent. Router}, false)})} pushStateFn = (URL) => {window.history.pushState({}, null, URL) } init = () => {window.addeventListener ('load', this.updateView, Window.addeventlistener (' popState ', this.updateView, false) is triggered when the page is loaded. Forward the History. The go () back () () is triggered when} updateView = () = > {const path = window. The location. The pathname | | '/'. If (this.route[path]) this.route[path]() if(this.route[path]) this.route[path]() }} new Router(routes) </script> </body> </ HTMLCopy the code
2020/12/24 Review – History route
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, "> < span style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 13px! Important; white-space: normal;" <a href="javascript:void(0)" data-href="/other"> <div id="content"> <script> const routes = [{path: '/home', component: '< /h1>'}, {path: '/other', component: '< /h1>'}, {path: '/other', component: '< /h1>'} '<h1>other page </h1>'}] class HistoryRouter {constructor(routes) {this.route = {} // route mapping key=path value=()=>{update view} This.createroutemap (routes) // Create the route mapping this.bindevent () // bind the event this.init() // initialize} createRouteMap = (routes) => {if (routes.length) { routes.forEach(({ path, component }) => { this.route[path] = () => { document.getElementById('content').innerHTML = component } }) } } bindEvent = () => { const a = document.getElementsByTagName('a') Array.prototype.forEach.call(a, aDom => { aDom.addEventListener('click', () => {const path = adom.getAttribute ('data-href') this.triggerPushState(path) // Triggers pushState}, False)})} triggerPushState = (path) => {window.history.pushState({}, null, path) // pushState() (1) This is just the case (click on the a TAB), using the pushState() function // (2) Case 2: Window.history.go () back() forward() case) // (3) case 3: This.updateview ()} updateView = () => {// because: Before executing the method, has triggered pushState () | | popstate event | | the load event / / so: Const currentPath = window.location.pathName? = window.location.pathName? window.location.pathname : '/' if (this.route[currentPath]) this.route[currentPath]() } init = () => { window.addEventListener('load', Window.addeventlistener (' popState ', this.updateView, false) // PopState is triggered, }} New HistoryRouter(routes) </script> </body> </ HTMLCopy the code
2021/07/25 Optimization – History route
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, Initial -scale=1.0" /> <title>Document</title> </head> <body> <a href="javascript:void(0)" data-href="/home">home</a> <a Href ="javascript:void(0)" data-href="/other">other</a> <div class="root">content</div> <script> / / - 1. Window. History. PushState (stateObj, title, url) and Windows. History. ReplaceState (stateObj, title, The popState event is not triggered. It does not refresh the browser, but it changes the history object and the URL address bar changes. // -window.history.go ()/back()/forward() // -browser forward, back button // history route implementation // -1. Add (data-href custom attribute) to each a tag, and bind each a tag (click event) to get the data-href, PushState ({}, null, data-href)) // -2. (window.history.pushState()); (window.location.pathName); (window.pathname); UI const routes = [{path: "/home", component: "<h1>home page </h1>",}, {path: "/home", component: "<h1>home page </h1>",}, {path: Component: "<h1>other page </h1>",},]; class HistoryRouter { constructor(routes) { this.route = {}; this.init(); this.createRouteMap(routes); // Mapping between (path) and (UI update function) this.bindevent (); } createRouteMap = (routes = []) => {routes. ForEach (({path, component }) => (this.route[path] = () => (this.DOM_CONTENT.innerHTML = component)) ); }; init = () => { window.addEventListener("load", this.updateView, false); window.addEventListener("popstate", this.updateView, false); this.DOM_CONTENT = document.getElementsByClassName("root")[0]; }; bindEvent = () => { const aList = document.getElementsByTagName("a"); [...aList].forEach((a) => { const path = a.getAttribute("data-href"); a.addEventListener( "click", (e) => { window.history.pushState({}, null, path); // window.history.pushState(state, title, URL), which changes the address bar url this.updateview (); // Update the view}, false); }); }; updateView = () => { const path = window.location.pathname; // Get the latest path this.route? .[path]? . (); }; } new HistoryRouter(routes); </script> </body> </ HTMLCopy the code
Manually implement a Vue-Router (hash version)
- The principle of
- The general principle is the same as the HTML version of hash routing, with minor differences
- Both use hash strings such as (‘#/ XXX ‘) in (href) of (a tag)
- Just click on the A TAB => The hash part of the URL in the address bar changes => Also triggers the HashChange event => Get the latest hash from window.location.hash
- Get the hash to match the path in the routeMap, and change the view when it matches
- The difference between
- The difference is that Vue encapsulates itself
<router-link>
和<router-view>
component - You can register the above two components through the Vue.component() method
- through
Vm.name can access the name in new Vue({data: {name: xx}})
- The difference is that Vue encapsulates itself
<router-link to="#/home">home</router-link> </router-link <router-view></router-view> // Define a new component named Vue.component('button-counter', {data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{count}} times.</button>'}) So they receive the same options as new Vue - such as data, computed, watch, methods, and lifecycle hooks. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Word-wrap: break-word! Important; word-wrap: break-word! Important; "> < img style =" text-align: center; - introduction of Vue introduced through CDN -- > < script SRC = "https://cdn.jsdelivr.net/npm/vue/dist/vue.js" > < / script > < / head > < body > < div id = "app" > <! -- Note that the router-link component has the to attribute --> <router-link to="#/home">home</router-link> <router-link To ="#/other">other</router-link> </router-view> </router-view> </div> <script> <h1>home page </h1>'} const Other = {template: '<h1> Other page </h1>'} // Create vue array const routes = [{path: '/home', component: Home }, { path: '/other', component: Other}] class VueRouter {constructor(Vue, option) {// constructor: Vue = option; $options = option this.routeMap = {} // routeMap {path: Component} this.createroutemap (this.options) // Create a route map this.app = new Vue({data: {currentHash: '#/'}}) // this.app.currenthash => the value of currentHash can be accessed '#/' // example // var data = {name: 'woow_wu7'} // var vm = new Vue({ // data: Data //}) // vm. Name === data.name => true this.init() // Initialize the listener this.initComponent(Vue) // Initialize the Vue type of components} CreateRouteMap = (option) => {// Note: option is the second argument passed to VueRoute, that is {routes: Routes} // Options is an object option.routes. ForEach (item => {this.routemap [item.path] = item.ponent // this.routemap is an object: {path: Component}})} init = () => {window.addeventListener ('load', this.onHashChange, false) DOMContentLoaded // Load: Triggers when the page is loaded, including when the DOM has been loaded, when all the resources such as images and videos have been loaded. Window.addeventlistener (' hashChange ', this.onHashChange, false) is fired when DOM is loaded. Hash change when} onHashChange = () = > {. This app. CurrentHash = window. The location. The hash. Slice (1) | | '/' / / / / (1) when hahs hasn't changed, Load event is triggered when the / / the window. The location. The hash = '= > window. The location. The hash. Slice (1) =' / / so: the situation: This.app.currenthash = '/' // (2) // when hash is changed, window.location.hash has a value, which is '#/... } initComponent = (Vue) => {// router-link component // props to // template is essentially treated as a tag, href is the to attribute passed in, Vue.component('router-link', {props: {to: {type: String, value: "}}, template: '<a :href="to"><slot/></a>' }) Vue.component('router-view', { render: (h) => {const Component = this.routemap [this.app.currenthash] // Return h(component) = createElement(component) // render: function(createElement) { return createElement(App); } } }) } } new VueRouter(Vue, { routes }) new Vue({ el: '#app' }) </script> </body> </html>Copy the code
data
URI and URL: www.luyuqiang.com/uri-url-urn… An example of the difference between A URI and a URL juejin.cn/post/684490… The composition of the URL (excellent) www.jianshu.com/p/406d19dfa… DOMContentLoaded and the load difference: www.jianshu.com/p/1a8a7e698… Window. Location object: wangdoc.com/javascript/… Vue-router simulation juejin.cn/post/684490… Hash History route simulation juejin.cn/post/684490… Vue-router source record juejin.cn/post/684490… VueRouter source analysis juejin.cn/post/684490…