What is the difference between link and import?

  • Link is an HTML tag that has no compatibility issues and can dynamically introduce stylesheets through JS DOM manipulation.
  • @import is an import style sheet syntax provided by CSS. It cannot be loaded dynamically and is not compatible with IE5.
  • Because link is an HTML tag, it introduces styles that are loaded at the same time the page is loaded, and @import needs to be loaded after the page is loaded.

Grail layout and double wing layout understanding and difference, and code implementation

Both the Grail layout and the Twin Wing layout are three-column layouts with fixed width of left and right boxes and adaptive middle boxes (solid ratio solid). The difference is the idea of their implementation. Grail layout:

<div id="header">#header</div>
<div id="container">
  <div id="center" class="column">#center</div>
  <div id="left" class="column">#left</div>
  <div id="right" class="column">#right</div>
</div>

<div id="footer">#footer</div>
// style
body {
  min-width: 600px; 
}
#container {
  padding-left: 200px;  
  padding-right: 200px; 
}
#container .column {
  height: 200px;
  position: relative;
  float: left;
}
#center {
  width: 100%;
}
#left {
  width: 200px;          
  right: 200px;        
  margin-left: -100%;
}
#right {
  width: 200px;         
  margin-right: -200px;
}
#footer {
  clear: both;
}

/*** IE6 Fix ***/
* html #left {
  left: 200px;
}
Copy the code

The holy Grail layout idea is to make the left and right padding of the content area to prevent occlusion, to make all three columns in the middle float left, to move the left and right content area to the top by using margin negative spacing, and to move the left and right content area to the target position by using relative + left and right Settings.

Twin wing layout:

<body> <div id="hd">header</div> <div id="middle"> <div id="inside">middle</div> </div> <div id="left">left</div> <div id="right">right</div> <div id="footer">footer</div> </body> <style> #hd{ height:50px; } #middle{ float:left; width:100%; /* Go to the first line */ height:100px; } #left{ float:left; width:180px; height:100px; margin-left:-100%; } #right{ float:left; width:200px; height:100px; margin-left:-200px; } #inside{margin:0 200px 0 180px;} #inside{margin:0 200px 0 180px; height:100px; } #footer{ clear:both; /* remember to float */ height:50px; } </style>Copy the code

Double wings layout: Create a sub-div for Middle and set margin-left right for the left and right columns. The rest is the same as the Holy Grail layout.

This can now also be easily implemented using Flex-Box.

What are the properties of transition and animation in CSS3

Transition-property (2) transition-duration (3) transition-timing-function (1) animation-name: animation name (2) animation-duration: (3) animation-timing-function: animation-delay: Delay (5) animation-iteration-count: number of animations (6) animation-direction: direction (7) animation-fill-mode: forbid mode

With recursive algorithm, array length is 5 and the random number of elements between 2 and 32 do not repeat the value

let array = new Array(5) const fillArray = (arr, index = 0, min = 2, max = 32) =>{ const num = Math.floor(Math.random() * (max - min + 1)) + min if(index < arr.length) { if(! arr.includes(num)) { arr[index++] = num } return fillArray(arr, index) } return arr } console.log(fillArray(array));Copy the code

Write a method to remove whitespace from a string

String. The split ('). The join (' ') / / or string. Replace (/ \ s/g, ' ')Copy the code

What are some ways to hide elements on a page?

visibility: hidden;
margin-left: -100%;
opacity: 0;
transform: scale(0);
display: none;
width: 0; height: 0; overflow: hidden;
Copy the code

Write a method that toggles the case of a string

let str = 'aBCdEFg'
const reverseStr = (val) =>{
	return val.split('').map(item=>{
		if(item.toLowerCase() === item) {
			return item.toUpperCase()
		} else {
			return item.toLowerCase()
		}
	}).join('')
}
console.log(reverseStr(str));
Copy the code

CSS3 new pseudo class has what and brief description

CSS3 specifies that pseudo-classes are represented by:; Pseudo-elements are represented by ::

This section describes the value and function of the hyperlink target attribute

_top is commonly used in frame and iframe. Load the target document directly into the top-level frame, loading the entire window.

What is the difference between a tag and a tag in a React-router?

is used with

in the React-Router to redirect routes. The React Router takes over the Link’s default jump Link behavior. Link does three main things

  1. If you have onclick, do onclick
  2. Prevent a TAB from default event when click (so that clicking 123 does not jump to and refresh the page)
  3. Get the jump href (to) and use history (history & hash) to jump to the page

Implementation principle of Single page application (SPA) routing

  1. Hash: Hash is intended to be used as an anchor for navigation up and down a long document, but not for SPA routing control. However, hashes can be used for routing control because they can change urls without refreshing the page, and because browsers also provide event monitors such as onHashchange.

  2. History: In the early days, history could only be used to jump to multiple pages. The following apis have been added to History in the HTML5 specification

    history.pushState(); // Add a new state to the history stack history.replacEstate (); // Replace the current state with the new state history.state // return the current state object

PushState or history.replaceState can also be used to change the URL without refreshing the page. However, onHashchange can listen for hash changes, but history changes cannot be monitored directly. You need to listen for history changes by intercepting ways that might change history. There are three ways you can change a URL

  • Click browser forward and backward
  • Click on the A TAB
  • The first type of route can be listened for by the onPopState event. The second and third types are actually the same. The default event of a tag can be disabled by JS

How do I configure the React Router

  1. When selecting router types, such as BrowserRouter and HashRouter, make sure they are rendered under the root directory
  2. Use Route matchers, switches, and routes. Typically Route is wrapped with Switch, which is used to render the first subroute or Redirect that matches the path.
  3. Jump to the destination route using the navigation component. You can use this if you want to force navigation
  4. You can navigate from inside the component using some Hooks provided with the React Router
  5. React allows you to load routing components dynamically using Lazy and Suspense components. You can lazily load unused components

Why use transform (why not marginLeft/Top)

Transform transform is a composite property. The transition/animation animation creates a composite layer. This allows the element to be animated in a separate layer. Typically, the browser will draw the contents of a layer into a bitmap and then upload it to the GPU as a texture. As long as the contents of the layer do not change, there is no need to repaint. The browser will recomposite the contents to form a new frame. Margin top/left Top /left belongs to the layout attribute, the change of this attribute will cause reflow/relayout, the so-called rearrangement refers to these nodes and other nodes affected by these nodes, CSS calculation -> layout -> redraw process, The browser needs to redraw the entire layer and re-upload it to the GPU, resulting in a significant performance overhead.

Large file fragments were uploaded and resumable

Ideas: The core is to use the blob.prototype. slice method. Similar to the array slice method, the slice method is called to return a slice of the original file so that we can split the file into slices according to the preset maximum number of slices. Call promise. all to upload multiple slices at the same time, so that the original large file is transferred to multiple small file slices at the same time, which can greatly reduce the upload time. In addition, due to concurrency, the order of transmission to the server may change, so we also need to record the order of each slice. When all fragments are successfully uploaded, the server is notified to merge the fragments. When a fragment fails to be uploaded, the message upload failed is displayed. In to upload, file upload state is obtained by file MD5, when the server has the MD5 corresponding section, on behalf of the section has been uploaded, no need to upload again, when the server can’t find the MD5 corresponding section, on behalf of the section need to upload, users only need to upload this part of the section, can complete the upload the entire file, This is a breakpoint continuation of the file.

Mobile adaption 1px problem

Cause: related to devicePixelRatio (DPR), which indicates the ratio of device pixel to CSS pixel when the default zoom is 100% : physical pixel /CSS pixel. The current mainstream screen DPR=2 (iPhone 8), or 3 (iPhone 8 Plus). For a 2x screen, the physical pixel of the device needs to be 1 pixel and the DPR=2, so the CSS pixel can only be 0.5. The 1px is 750, and the CSS style is 375, so we should write 0.5px. IOS 8+ is supported, Android is not.

My usual solution is to use pseudo-elements, which are absolutely positioned and aligned with the upper-left corner of the parent element. First enlarge the length and width of the fake element by 2 times, then set a border with the top left corner as the center and scale to 0.5 times the original size. Besides this method, you can also use images or box-shadow instead, but it is not as good as the fake element.

Shallow copy and deep copy

First, there are two types of data types, a basic data type (String, Number, Boolean, Null, Undefined, Symbol) and reference data type (Array,Object).

Basic data types are stored directly in stack memory. A reference data type stores a pointer on the stack to the starting address of the entity in the heap. When the interpreter looks for a reference value, it first retrieves its address in the stack and then retrieves the entity from the heap.

The difference between a deep copy and a shallow copy is that a shallow copy copies only Pointers to an object, not the object itself, and the old and new objects still share the same memory. But deep copy will create another identical object, the new object and the original object do not share memory, modify the new object will not change to the original object.

The difference between shallow copy and assignment is as follows: The assigned object and the original object point to the same storage space. No matter which object is changed, it is the content of the changed storage space. Therefore, the two objects are linked. A shallow copy creates a new object. If the property is of a primitive type, it copies the value of the primitive type. If the attribute is a memory address (reference type), the memory address is copied. Changing any attribute of the assigned object changes the original object. However, changing the attribute of the base type of the shallow copy object does not change the value of the base attribute of the original object. Changing the attribute of the reference type changes the corresponding value of the original object.

Shallow copy implementation

  1. Object.assign
  2. Array.prototype.slice()
  3. Array.prototype.concat()
  4. Deconstruction assignmentlet { ... x } = obj;

Deep copy implementation

  1. JSON.parse(JSON.stringify())
  2. lodash.cloneDeep
  3. Deep copy is a deep copy that iterates through objects and arrays by hand until they are full of primitive data types

Can forms cross domains? Tell me what you know about cross domains

Answer: Forms can cross domains. First of all, the cross-domain problem is caused by the same origin policy of the browser. Network requests without the same origin policy may lead to CSRF attacks, that is, the attacker steals your identity and sends malicious requests in your name, because the browser will automatically attach cookies to the header field cookie of HTTP requests. Therefore, the server will assume that the attacker’s operation is your own operation, so the browser by default disables cross-domain requests.

Common solutions:

  1. JSONP handles GET requests
  2. Cross-domain resource sharing CORS (Backend configuration required, common practice)
  3. Nginx reverse proxy addresses cross-domain. Nginx is a lightweight HTTP server that can be used as a reverse proxy on the server. In reverse proxy, the proxy server receives the request, forwards the request to the server on the internal network, and returns the result to the client. In this case, the proxy server acts as a server externally. We can take advantage of this feature to handle cross-domain problems by forwarding requests to real back-end domains.

Back to the form form, it’s also cross-domain, because the form submission doesn’t carry cookies, and you can’t set a hidden form entry and get cookies from other domains through JS, because cookies are dome-based and you can’t access cookies from other domains. Therefore, the browser believes that form submission to a field cannot take advantage of the cookie and session in the cookie established between the browser and the field. Therefore, the browser does not limit the cross-domain problem of form submission.

The essence of the browser same-origin policy is that the JS of one domain name cannot read the content of another domain name without permission. But the browser doesn’t prevent you from sending a request to another domain.

Microtasks, macro Tasks, and Event Loops

All tasks can be categorized into two types, synchronous and asynchronous. A synchronization task refers to a task that is queued to be executed on the main thread. The next task can be executed only after the first task is completed. Asynchronous tasks are tasks that do not enter the main thread but enter the task queue. The task queue notifies the main thread that an asynchronous task is ready to execute. Operation mechanism:

(1) All synchronization tasks are executed on the main thread, forming an execution context stack. (2) In addition to the main thread, there is a task queue. Whenever an asynchronous task has a result, an event is placed in the "task queue". (3) Once all synchronization tasks in the "execution stack" are completed, the system reads the "task queue" to see what events are in it. Those corresponding asynchronous tasks then end the wait state, enter the execution stack, and start executing. (4) The main thread repeats step 3 above.Copy the code

This mechanism is also known as an Event Loop.

Both macro and micro tasks are asynchronous tasks, the main difference being their order of execution. Macro tasks: including overall code script, setTimeout, setInterval, and setImmediate. Microtasks: Native Promises (some implemented promises put then methods in macro tasks), process.nextTick, MutationObserver

Js async has a mechanism, that is, when you encounter a macro task, you execute the macro task first, put the macro task in the event queue, and then execute the micro task, put the micro task in the event queue, and the most interesting thing is that these two queues are not the same queue. When you go out, you take the callback function from the microtask, and then you take the callback function from the macro task queue.

Example 1:

setTimeout(()=>{
  console.log('setTimeout1')
},0)
let p = new Promise((resolve,reject)=>{
  console.log('Promise1')
  resolve()
})
p.then(()=>{
  console.log('Promise2')    
})
Copy the code

Output result: Promise1, Promise2, setTimeout1 Promise itself is a synchronous immediate function, Promise1 is printed out as synchronous code, callbacks go into the microtask queue because promises are microtasks, After the synchronization task is completed, the value in the micro task queue will be completed first, and then the value in the macro task queue will be taken.

Example 2:

Promise.resolve().then(()=>{
  console.log('Promise1')  
  setTimeout(()=>{
    console.log('setTimeout2')
  },0)
})

setTimeout(()=>{
  console.log('setTimeout1')
  Promise.resolve().then(()=>{
    console.log('Promise2')    
  })
},0)
Copy the code

The output is Promise1, setTimeout1, Promise2, setTimeout2

  1. Look at the microtask queue, extract the value in the microtask queue, and print Promise 1.
  2. Generate an asynchronous task macro task setTimeout2.
  3. The microtask queue is empty, look at the macro task queue, setTimeout1 before setTimeout2, fetch setTimeout1
  4. Generate a promise2 microtask
  5. Clears the values in the microtask queue and outputs Promise2.
  6. View the macro task queue and print settTimeOut2

SetTimeOut, Promise, async/await

Consider the difference between the three in the event loop, which is divided into macro task queue and micro task queue.

  1. The setTimeout callback is placed in the macro task queue until the execution stack is empty.
  2. The promise.then callback will be placed in the microtask queue until the synchronous code in the macro task completes.
  3. An async function returns a Promise object. When the function executes, it returns an await and waits until the triggered asynchronous operation is complete before executing the following statement in the function body. It can be understood as giving up the thread, out of the async function body.

Promise

The object represents the final completion (or failure) of an asynchronous operation and its resulting value.

The method of promise

1. Promise.resolve(value)

Returns a Promise object whose state is determined by the given value.

  1. If the value passed in is itself a Promise object, that object is returned as the return value of the promise.resolve method.
  2. If the value is thenable(that is, the object with the THEN method), the final state of the returned Promise object is determined by the then method execution
  3. Otherwise, return a Promise object whose state has changed to Resolved.

2. Promise.reject

Class method, and the only difference with resolve is that the return promise object has a state of Rejected.

3. Promise.all

Class method, multiple Promise tasks executed simultaneously. If all are successfully executed, the results of all Promise tasks are returned as an array. If there is a Promise task Rejected, only the result of the Rejected task is returned.

4. Promise.race

Class method, which executes multiple Promise tasks at the same time and returns the result of the first completed Promise task executed, whether the Promise result succeeds or fails.

5. Other

Instance methods:

  • Promise.prototype.then registers callback functions for promises
  • Promise.prototype.catch instance method to catch exceptions

State of Promise

Promise objects have three states, and once a state changes, it can’t be changed to another state.

Pending: The asynchronous task is in progress. Resolved (which can also be called a pity), this asynchronous task will be successfully executed. The asynchronous task fails to be executed

Used to summarize

You first initialize a Promise object, which can be created in two ways, both of which return a Promise object.

1, new Promise(fn) 2, Promise.Copy the code

Then call the then method of the Promise object returned in the previous step to register the callback function. Finally, register the catch exception handler,

Promise All implementation

  1. Receive an array of Promise instances or an object with an Iterator interface,
  2. Resolve becomes a Promise object if the element is not a Promise object
  3. If everything succeeds and the state becomes resolved, the returned values will be passed as an array to the callback
  4. Once there is a failure, the state changes to Rejected and the return value is passed directly to the callback
  5. The return value of promise.all () is also the new Promise object

Async/Await internal implementation

What does Async do

Async returns a Promise object. If you return an immediate Promise in the function, async wraps the immediate Promise object with promise.resolve ().

Await waiting for what

Await can be used to wait for the return value of an async function. Notice that await is not used to wait for a Promise object, it can wait for the result of any expression. Therefore, await can be followed by ordinary function calls or direct quantities.

Await await, and then

If it waits for something other than a Promise object, the result of the await expression operation is what it waits for.

If it waits for a Promise object, await is busy and blocks the following code, waiting for the Promise object resolve, and then getting the value of resolve as the result of the await expression.

What are the advantages of async/await?

The advantage of async/await is in handling then chains, especially if each step requires the result of each previous step. Async /await code is very clear compared to promise, almost like synchronous code.

Realize the principle of

Async /await is the syntactic sugar of the Generator, making asynchronous operations more convenient. The async function replaces the asterisk (*) of a Generator function with async and yields with await. The difference is:

  1. Async function built-in executor, function call, will be automatically executed, output the final result. The Generator calls next.
  2. The return value is a Promise, the async function returns a Promise object, and the Generator returns an Iterator. Promise objects are more convenient to use.

Simple practice code:

Function asyncToGenerator(generatorFunc) {return function() {// Call generator to generate iterator const gen = generatorFunc.apply(this, arguments) return new Promise((resolve, reject) => { function step(key, arg) { let generatorResult try { generatorResult = gen[key](arg) } catch (error) { return reject(error) } const { value,  done } = generatorResult if (done) { return resolve(value) } else { return Promise.resolve( value ).then( function onResolve(val) { step("next", val) }, function onReject(err) { step("throw", err) }, ) } } step("next") }) } }Copy the code

How to avoid writing a try/catch to each async

Write an auxiliary function:

async function errorCaptured(asyncFunc) {
    try {
        let res = await asyncFunc()
        return [null, res]
    } catch (e) {
        return [e, null]
    }
}
Copy the code

Usage:

async function func() { let [err, res] = await errorCaptured(asyncFunc) if (err) { //... Error catch} //... }Copy the code

Mobile adaptation

  1. Rem adaptation: The essence of the layout is equal scale scaling, by dynamically setting the HTML font size to change the REM size.
    • Dynamic rewrite<meta>The scale in the tag
    • to<html>Element adds a data-dPR attribute and dynamically overwrites the value of data-dPR
    • to<html>Element adds a font size attribute and dynamically overwrites the value of font size
    • Use the plugin to convert PX to REM.
  2. Vw solution: If the design draft uses 750px width, 100VW = 750px, that is, 1VW = 7.5px. Then we can directly convert the px value on the design drawing into the corresponding VW value. If you don’t want to do it yourself, you can use the PostCSS plugin postCSs-px-to-viewport, which allows you to write px directly in your code.
  3. With REM and VW, you can dynamically change the size of the root element by setting it in VW units that change with the viewport. Limit the maximum and minimum font size for the root element, along with the body plus the maximum and minimum widths

closure

Simply put, a closure is a function that has access to a variable in the scope of another function. The most common way to create closures is to create or return another function inside one function. Such as:

var a = function () {
  var test = {};
  setTimeout(function () {
    console.log(test);
  }, 1000);
}
Copy the code

In the example above, test is defined in A, but a reference is kept to it in the argument (function) of setTimeout. When a is executed, even though it has already been executed, theoretically any variables or objects created during the execution of a can be destroyed. Test, however, is referenced, so it cannot be destroyed at the end of the function’s execution until the timer function is executed.

Anti-shake and throttling

Anti-shake: Optimizes multiple high-frequency operations to be executed only for the last time. The scenario is as follows: User input is completed and input verification is performed only once.

Implementation logic: Execute the callback n seconds after the event is triggered, and if it is triggered again within n seconds, the timer is reset. Implementation code:

// timer const debounce = (fn, ms = 0) => {let timeoutId; return function(... args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn.apply(this, args), ms); }; };Copy the code

Throttling: Perform it once every period of time, that is, reduce the frequency and optimize the high frequency operation into the low frequency operation. It is usually used in the scenario of scrollbar event or REsize event. It is usually performed once every 100~500 ms.

Implementation logic: specifies that a function can only fire once in a unit of time. If the function is fired multiple times per unit of time, only one time will be effective:

// timer const throttle = function (func, delay) {let timeoutId = null; return function (... args) { if (! timeoutId) { timeoutId = setTimeout(function () { func.apply(this, args); timeoutId = null }, delay); }} // const throttle = function(func, delay) {let prev = date.now (); return function(... args) { let now = Date.now(); if (now - prev >= delay) { func.apply(this, args); prev = Date.now(); }}}Copy the code

Prototype and prototype chain

JavaScript creates instances not through classes but directly through constructors.

function Dog(name, color) {
    this.name = name
    this.color = color
    this.bark = () => {
        console.log('wangwang~')
    }
}

const dog1 = new Dog('dog1', 'black')
const dog2 = new Dog('dog2', 'white')
Copy the code

The above code is the process of declaring a constructor and creating an instance from the constructor. In the code above, two instances are created with their own names and colors, but their Bark methods are the same, and when you create an instance with a constructor, you have to recreate the method and add it to the new instance, resulting in a lot of waste.

Prototype is used. Each constructor has a Prototype property that defines a shared method so that the methods on both instances point to the same location.

Person.prototype.bark = function() {
  console.log("wangwang~~");
}
Copy the code

All objects in JavaScript are inherited from their prototype objects. And the prototype object itself is also an object, it also has its own prototype object, so layer upon layer, forming a structure similar to a linked list, this is the prototype chain. The relationship between prototype chains and prototypes can be summarized in the following diagram.

This, bind, call, apply

This always refers to the object that last called it.

1. Use the arrow functions of ES6

The arrow function’s this always points to this when the function is defined, not when it is executed.

2. Use _this = this inside the function

3. Use apply, call and bind

Apply, call, and bind can all change the direction of this, but these three functions are slightly different

  1. fun.call(thisArg[, arg1[, arg2[, …]]])
  2. fun.apply(thisArg, [argsArray])

Call is similar to Apply except that the call method is different in that Apply accepts only two objects: a new This object and an array of parameters. Call can take a this object and multiple arguments

Example:

function add(a, b){ return a + b; } function sub(a, b){ return a - b; Var a1 = add. Apply (sub, [4, 2]); Var a2 = sub.apply(add, [4, 2]); a1; // 6 points sub to add, so add a2 is executed; Var a1 = add.call(sub, 4, 2);Copy the code

The difference between these methods and bind is that they are called immediately. Bind () does not call immediately and needs to be called manually: example:

window.onload = function() { var fn = { num: 2, fun: function() { document.getElementById("box").onclick = (function() { console.log(this.num); }).bind(this); // }).call(this); // }).apply(this); } /* * this is fun, so num can be accessed correctly, * if bind() is used, 2 will be printed after the click; * If call() or apply() is used, 2 */} fn.fun() will be printed when the page is refreshed; }Copy the code

Js design pattern

1. Factory mode

Create a function that returns the same properties and methods and can be called countless times. Often used to produce a large number of similar goods, to do the same thing, to achieve the same effect.

2. Singleton mode

Definition: Ensures that a class has only one instance and provides a global access point to access it. This ensures that a class has only one instance object, by checking if the instance exists and returning if it does, or by creating and returning if it does not.

Application scenario: A single object. For example, popovers should only be created once, no matter how many times they are clicked.

3. Strategic mode

Definition: Define a set of algorithms, encapsulate them one by one, and make them interchangeable.

The purpose of the strategy pattern is to separate the use of the algorithm from the implementation of the algorithm.

Example:

Var levelOBJ = {"A": function(money) {return money * 4; }, "B" : function(money) { return money * 3; }, "C" : function(money) { return money * 2; }}; /* Environment class */ var calculateBouns =function(level,money) {return levelOBJ[level](money); }; console.log(calculateBouns('A',10000)); / / 40000Copy the code

4. Proxy mode

Definition: Provides a proxy or placeholder for an object to control access to it.

Common form of virtual proxy: an expensive operation can be delayed until it is needed by virtual proxy (example: lazy image loading using virtual proxy)

The mediator pattern

Definition: A mediator object through which all other related objects communicate, rather than referring to each other, only notifies the mediator object when one of them changes. The mediator pattern can be used to decouple objects from each other.

Publish and subscribe

The publish-subscribe model is a one-to-many dependency between objects. When the state of an object changes, all dependent objects are notified of the state change.

Subscriber registers the Event they want to Subscribe to the Event Channel. When Publisher publishes the Event to the Event Channel, that is, when the Event is triggered, The processing code registered with the dispatch center by the Fire Event subscriber. Example: Vue’s EventBus

Observer model

The observer pattern also defines a one-to-many dependency between objects, so that when the state of each dependent object changes, its dependent objects are notified and automatically updated. Its goals are consistent with the publish-subscriber model.

The observed object adds and deletes an observer through the SUBSCRIBE and unsubscribe methods, and pushes messages to the observer through the broadcast method.

document.body.addEventListener('click', ()=>{}};
Copy the code

The above example is the simplest observer pattern. Document. body in this case is the observed object, and the global object is the observer, who calls the clickHandler method when the Click event is triggered.

Differences from the published subscriber model: The observer pattern in subject and observer there are still some coupling, and release the subscriber mode, the introduction of news dispatch center between the subject and the observer, all the messaging process through the message control center is completed, that is to say, specific business logic code will be in the news dispatch center, and realized completely loose coupling between the subject and the observer, The problem, meanwhile, is that the program becomes less readable.

Array judgment mode

1. Array.isArray()

2. instanceof

Instanceof is used to check whether the constructor’s Prototype property appears on the prototype chain of an instance object. grammar

object instanceof constructor
Copy the code

So if the Array constructor is found on the prototype chain of the Object, then the Object should be an Array, and vice versa

const a = []; console.log(a instanceof Array); //trueCopy the code

3. Object.prototype.toString

You cannot call the toString() method of the array itself directly, because it returns the string of the contents. Only the object’s toString method returns the type of the object. So we need to “borrow” the object’s toString method and use either call or apply to change the execution context of the toString method.

const a = ['Hello','Howard']; Object.prototype.toString.call(a); //"[object Array]"Copy the code

4.constructor

The instantiated array has a constructor property that points to the method that generated the array.

const a = []; console.log(a.constructor == Array); //trueCopy the code

However, the constructor attribute can be overwritten, and once overwritten, this method of judgment becomes invalid.

Array to heavy

  1. […new Set(array)]

    A set is a new data structure provided by ES6. It is similar to an array, but the values of its members are unique.

  2. For loops are nested and splice is de-weighted

  3. Create an empty result array, loop through the original array, check whether the result array has the current element, skip if they have the same value, push into the array if they do not. Methods to determine whether or not there are indexOf,array.includes

  4. Using the filter

    Arr. Filter (function(item, index, arr) {return arr. Filter (function(item, index, arr) {return arr. Return arr.indexof (item, 0) === index; }); }

Js data type

Seven primitive types:

  • Boolean
  • Null
  • Undefined
  • Number
  • BigInt
  • String
  • Symbol Reference type
  • Object
  • Array

MVC,MVP,MVVM

MVC(model,view,controller)

MVC not only divides the application into View and Model layer, but also adds an additional Controller layer, which is responsible for the application logic of the collaboration between Model and View (routing, input preprocessing, etc.). Model handles the business logic.

After the user performs an operation on the View, the View catches the operation and passes the processing right to the Controller (Pass calls). The Controller preprocesses the data from the View and decides which Model interface to call. The Model then executes the relevant business logic; When the Model changes, the View is notified via the Observer Pattern. When the View receives a message from the Model in observer mode, it asks the Model for the latest data and then updates the interface again.

Advantages:

  1. Separation of business logic and presentation logic, high degree of modularization. And when the application logic needs to change, there is no need to change the business logic and presentation logic, just need to change the Controller into another Controller (Swappable Controller).

  2. The observer mode allows multiple views to be updated simultaneously. Disadvantages:

  3. Controller test difficulty

  4. View cannot be componentized. A View is strongly dependent on a particular Model, and it becomes difficult to pull that View out as a reusable component for another application. Because the Domain Model of different programs is different.

MVP

MVP mode replaces Controller in MVC mode with Presenter.

Just like the MVC pattern, user actions on the View are transferred from the View to the Presenter. Presenter executes application logic and performs operations on the Model. The Model, after executing the business logic, also sends messages about its changes through observer mode, but to the Presenter instead of the View. Presenter updates the interface provided by the View after receiving a message about a Model change.

advantages

  1. The test is simple
  2. It can be componentized

disadvantages

  1. In addition to the application logic, there is also a large amount of View->Model, Model->View manual synchronization logic, which makes Presenter cumbersome and difficult to maintain.

MVVM(Model-View-ViewMode)

“ViewModel” means “Model of View”.

MVVM is called in the same way as MVP. However, there is a Binder in the ViewModel, which handles all the data synchronization between the View and the Model that was previously done by presenters. All you need to do is specify, in the View template syntax, which part of the Model is bound to the content displayed on the View. Binder automatically updates data to the View when the ViewModel pair is updated to the Model, and automatically updates data to the Model when the user performs operations on the View (such as form input). This approach is called two-way data binding.

advantages

  1. Easy to maintain
  2. Can be componentized
  3. To simplify the test

Disadvantages:

  1. For a large graphical application with a large number of view states, the cost of building and maintaining a ViewModel can be high

What is the life cycle of Vue?

  • Create: beforeCreate, created;
  • Load: beforeMount, mounted;
  • Update: beforeUpdate, updated;
  • Destroy: beforeDestroy, destroyed;

Vue component communication

1. props/$emit

2.
c h i l d r e n / children/
parent

The child instance can access the parent instance through this.$parent, and the child instance is pushed into the parent’s $children array, where it represents all methods and data that can access the component. This.$parent is an object and $children is an array.

3. provide/ inject

Provide/Inject is a new API in Vue2.2.0. Simply put, provide variables in the parent component and inject variables in the child component.

Note: As long as inject is called, it is possible to inject data in provide, regardless of how deeply nested the child component is, rather than being limited to returning data from the props property of the current parent component.

Example: A is the parent of B, and B is the parent of C

// A.vue <template> <div> <comB></comB> </div> </template> <script> import comB from '.. /components/test/comB.vue' export default { name: "A", provide: { for: "demo" }, components:{ comB } } </script> // B.vue <template> <div> {{demo}} <comC></comC> </div> </template> <script> import comC  from '.. /components/test/comC.vue' export default { name: "B", inject: ['for'], data() { return { demo: this.for } }, components: { comC } } </script> // C.vue <template> <div> {{demo}} </div> </template> <script> export default { name: "C", inject: ['for'], data() { return { demo: this.for } } } </script>Copy the code

4. ref/this.$refs

If used on a normal DOM element, the reference refers to the DOM element. When used on a child component, the reference refers to the component instance, through which you can directly invoke the component’s methods or access data.

5. Vuex

6. LocalStorage localStorage/sessionStorage

7.
a t t r s with Attrs and
listeners

If three nested components A->B,B->C, and need to assign values to C components in A and listen for EMIT events for C components, you can use $listeners and $listeners introduced by Vue2.4.0, and the new inheritAttrs option.

// A component... The < div > < h2 > component A data item: {{myData}} < / h2 > < B @ changeMyData = "changeMyData" : myData = "myData" > < / B > < / div >... // B component... The < div > < h3 > component B < / h3 > < C v - bind = "$attrs" v - on = "$listeners" > < / C > < / div >... <script> import C from './C' export default { components: { C }, inheritAttrs: false, props: ['pChild1'], mounted () { this.$emit('onTest1') } } </script> ... // C component <template> <div> < H5 > Component C</h5> < INPUT V-model ="myc" @input="hInput" /> </div> </template> <script> export default { props: { myData: { String } }, created() { this.myc = this.myData; // Console. info(this.$attrs, this.$listeners); }, methods: { hInput() { this.$emit("changeMyData", this.myc); // // events passed in component A}}}; </script>Copy the code

Note that the inheritAttrs attribute is used to determine whether the component’s root element inherits properties that it doesn’t inherit from the parent component. We set the inheritAttrs attribute to false in the example below

// Defaults to true

/ / to false

8.EventBus

Create the EventBus method: import the Vue and export an instance of it, or initialize it directly in main.js so that the EventBus we get is a global EventBus

Vue.prototype.$bus = new Vue()
Copy the code

Then you can publish subscription events via on/off/emit.

React Component Communication

Parent -> Child component prop pass

Child -> Parent component

  1. The parent component defines the method setValue directly by passing it to the child component, which internally calls the parent component method directly to change state

Brother components

  1. context
  2. State management library
  3. Publish subscriptions, similar to Vue’s eventBus

Vue responsive principle

The principle of

When you pass an ordinary JavaScript object into a Vue instance as the data option, Vue iterates through all of the object’s properties, And use Object.defineProperty to turn all of these properties into getters/setters. They allow Vue to track dependencies and notify property changes when they are accessed and modified.

Each component instance corresponds to a Watcher instance, which records “touched” data properties as dependencies during component rendering. Watcher is then notified when the setter for the dependency fires, causing its associated component to be re-rendered.

But Vue cannot detect array and object changes.

  • For objects:

Vue cannot detect the addition or removal of property. Since Vue performs getter/setter conversions on property when it initializes the instance, the property must exist on the data object for Vue to convert it to reactive. However, you can add responsive properties to nested objects using the vue.set (Object, propertyName, value) method.

  • For arrays:

    • When you set an array item directly using an index, for example, vm.items[indexOfItem] = newValue
    • When you modify the length of an array, for example, vm.items. Length = newLength

    These two conditions cannot be monitored

Since Vue does not allow you to dynamically add root-level reactive properties, you must declare all root-level reactive properties, even if they are null, before initializing the instance.

Asynchronous update queue

Vue is executed asynchronously when updating the DOM. As long as it listens for data changes, Vue opens a queue and buffers all data changes that occur in the same event loop. If the same watcher is triggered more than once, it will only be pushed into the queue once. This removal of duplicate data while buffering is important to avoid unnecessary computation and DOM manipulation. Then, in the next event loop, “TICK,” Vue refreshes the queue and performs the actual (de-duplicated) work. Vue internally attempts to use native Promise.then, MutationObserver, and setImmediate for asynchronous queues, and setTimeout(fn, 0) instead if the execution environment does not support it.

When you set vm.someData = ‘new Value ‘, the component does not immediately re-render. When the queue is refreshed, the component is updated in the next event loop “TICK”. To wait for Vue to finish updating the DOM after the data changes, use vue.nexttick (callback) immediately after the data changes. This callback will be called after the DOM update is complete.

$nextTick(function () {console.log(this.$el.textContent) // => 'Updated'})Copy the code

Because $nextTick() returns a Promise object, you can do the same thing using the new ES2017 async/await syntax:

methods: { updateMessage: Async function () {this.message = 'updated' console.log(this.$el.textContent) // => 'unupdated' await this.$nextTick() Console. log(this.$el.textContent) // => 'Updated'}}Copy the code

React Core Principles

Understanding the Virtual DOM

The Virtual DOM is actually an abstraction of the actual DOM, a JS object. React all of its surface operations are actually manipulating the Virtual DOM.

The internal logic is: use JavaScript objects to represent DOM information and structure, and build a real DOM tree based on the tree structure represented by JavaScript objects. When the state changes, the newly rendered object tree is compared with the old tree to record the difference between the two trees (diff algorithm). The difference recorded is that we need real DOM operations on the page, then apply them to the real DOM tree, and the page changes. That’s it: the structure of the view is indeed completely new, but it does change only in different ways when you finally manipulate the DOM.

DOM is slow, a simple div element can print a lot of stuff, and careless manipulation can lead to page rearrangements. Native JavaScript objects are faster and simpler to process than DOM objects. The structure and attribute information of the DOM tree can be easily represented as JavaScript objects. Since the information in the DOM tree can be represented in JavaScript objects, you can, in turn, build a real DOM tree based on the tree structure represented in JavaScript objects.

The Virtual DOM is essentially a cache between JS and DOM. The analogy is CPU and hard disk, since the hard disk is so slow, we put a cache between them: since DOM is so slow, we put a cache between them, JS and DOM. JS only manipulates the Virtual DOM and writes changes to the DOM at the last minute.

JSX

JSX (Javscript) is a syntax extension for JavaScript. CreateElement (Component, props,… The syntactic sugar of the children function. The react. createElement function most often generates an object, which we call the React object or another name — the virtual DOM.

  • You can use it as the value of a variable in the if and for loops
  • You can also pass it as an argument to the function
  • It can also be returned as the return value of a function.
  • Variables in JSX are wrapped with {} to protect against XSS attacks

Server side rendering

React supports server-side rendering.

Why server Side Rendering (SSR)? This is closely related to the rise of single page apps (SPA). Compared with traditional SSR applications, SPA has great advantages in speed and user experience. But there’s a problem. The initial server request for a SPA usually returns an HTML file with no DOM structure, just a bunch of CSS and JS links. The application then needs to fetch some additional data to render the associated HTML tags. This means that users will have to wait longer for the initial rendering. This also means that a crawler might parse your page empty. Therefore, the solution to this problem is to render your app on the server first (render the first screen) and then use SPA on the client.

SSR advantages

  • Improved first screen rendering time
  • Complete indexable HTML pages (good for SEO)

We can use next. Js to build React applications that support server-side rendering.

The data flow

React data flows are one-way data flows from top to bottom.

React latest life cycle

  1. mount
    • constructor()
    • static getDerivedStateFromProps()
    • render()
    • componentDidMount()
  2. update
    • static getDerivedStateFromProps()
    • shouldComponentUpdate()
    • render()
    • getSnapshotBeforeUpdate()
    • componentDidUpdate()
  3. uninstall
    • componentWillUnmount()
  4. When an error is thrown
    • static getDerivedStateFromError()
    • componentDidCatch()

Three life cycles to be abolished

  • UNSAFE_componentWillMount()
  • UNSAFE_componentWillUpdate()
  • UNSAFE_componentWillReceiveProps()

static getDerivedStateFromProps

GetDerivedStateFromProps is called before the Render method is called, and is called both during the initial mount and during subsequent updates. It should return an object to update state, and if null is returned, nothing is updated. When props change, it is recommended to use update getDerivedStateFromProps life cycle state, UNSAFE_componentWillReceiveProps is about to be abandoned

getSnapshotBeforeUpdate

GetSnapshotBeforeUpdate () is called before the last render output (submitted to the DOM node). It enables the component to capture some information (for example, scroll position) from the DOM before changes are made. Any return value for this life cycle is passed as an argument to componentDidUpdate().

What is the difference between computed and Watch in Vue

Computed attributes (computed)

Suitable for scenarios where you need to obtain results from complex calculations that depend on one or more variables. Such as:

computed:{
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
}
Copy the code

You can achieve the same effect by calling methods in expressions, except that evaluated properties are cached based on their reactive dependencies. They are reevaluated only when the associated reactive dependencies change. This means that as long as the Message has not changed, multiple visits to the reversedMessage computed property will immediately return the previous computed result without having to execute the function again.

Listening properties (Watch)

Watch watches for changes in the evaluation of an expression or a function on a Vue instance. The callback takes new and old values. The expression accepts only supervised key paths (‘ A.B.C ‘). For more complex expressions, replace them with a function.

In addition, it has two attributes deep and immediate

You can perform any logic in Watch, such as function throttling, Ajax asynchronously fetching data, and even DOM manipulation (not recommended)

Their differences

  • Watch: Monitors the property value. Whenever the property value changes, it triggers the execution of a callback function to perform a series of operations;
  • Computed: Monitors dependency values. If the dependency values remain the same, it directly reads the cache for reuse, and recalculates only when they change.
  • A slightly important difference is that computed properties cannot perform asynchronous tasks; computed properties must be executed synchronously. This means that computed properties cannot request or perform asynchronous tasks to the server. If an asynchronous task is encountered, it is handed to the listening property. Watch can also detect computed attributes.

conclusion

Computed attributes are suitable for template rendering, where a value is computed depending on other responsive objects or even computed attributes. The listening attribute is suitable for observing changes in a value to complete a complex piece of business logic.

The React shallow comparison

Because the PureComponent’s shouldeComponentUpdate is actually a shallow comparison of props/state, it does not apply to nested objects. This is because the React shallow comparison only compares the value of an Object with the basic data type when the key is of the same length as Object. It is possible that comparisons do not match expectations, so shallow comparisons are not suitable for nested types

React vs. Vue

1. Different principles for monitoring data changes

  • With getters/setters and some hijacking of functions, Vue knows exactly how the data is changing and does not require special optimization to achieve good performance
  • React the default was conducted by means of comparative reference, if not optimal (PureComponent/shouldComponentUpdate) may lead to a lot of unnecessary VDOM to render

2. Differences in data flow

  • Vue supports bidirectional binding
  • React is a one-way data stream, called onChange/setState() mode.

3. Different template rendering methods

  • React renders templates using JSX. Deep down, React renders templates using native JS implementations of common syntax (such as interpolation, conditional, loop, etc.)

  • Vue is rendered using an extended HTML syntax. It is implemented in a separate template from the component’s JS code through instructions, such as conditional statements that require V-if

  • The Render function in React supports closures, so the components we import can be called directly in Render. In Vue, however, we import a component and declare it in components because the data used in the template must hang on this for a transit.

React How to check and change data

Vue hijacked the get and set methods of objects through Object.defineProporty to achieve bidirectional binding. React, by contrast, is a UI rendering framework for one-way data flow. There is no data detection mechanism in React itself, and all data changes are manually implemented through setState.

Both Vue and React implement the concept of “virtual DOM” internally, which means that the real DOM to be rendered is virtualized into a JS object. During rendering, the minimum operation required to render the real DOM is calculated by comparing the old and new JS objects to optimize performance. React and Vue both have their diff algorithms, which work similarly.

React High Order Component (HOC)

The concept of higher-order components should be derived from JavaScript higher-order functions:

A higher-order function is a function that takes a function as input or output, and a higher-order component (HOC) is a function that takes a group of components as input and returns a component. HOC does not modify an incoming component, nor does it use inheritance to replicate its behavior. Instead, HOC makes up new components by wrapping them in container components. HOC is a pure function with no side effects. It’s actually grammar candy for the decorator.

React also used mixins before higher-order functions, but the heavy use of mixins in engineering can cause problems,

  1. Breaking component encapsulation: Mixins may introduce invisible properties. For example, using Mixin methods in rendering components introduces invisible properties (props) and state to the component. And mixins can be interdependent and coupled to each other, which is not conducive to code maintenance.
  2. Methods in different mixins can conflict with each other

What can HOC do

He can:

  1. Composite rendering, conditional rendering
  2. Operating props
  3. Get refs
  4. The operating state

Advantages of using HOC

  1. Extract repetitive code to realize component reuse. Common scenario: page reuse.
  2. Conditional rendering, controlling the rendering logic of components (render hijacking), common scenarios: permission control.
  3. Capture/hijack the life cycle of the component being processed, common scenarios: component rendering performance tracking, logging.

Disadvantages of using HOC

  1. HOC needs to be wrapped or nested on top of the original components, and if you use HOC in large amounts, you get a lot of nesting, which makes debugging very difficult.
  2. HOC can hijack props and can cause conflict if conventions are not followed.

React Hooks

Hooks are a new feature added in 16.7. Its advantages are

  1. Reduce the risk of state logic reuse
  2. Avoid hell of nesting
  3. Make components easier to understand

Write a custom Hook

export const useInterval = (callback, delay) => { const savedCallback = useRef(); UseEffect (() => {savedcallback.current = callback; }, [callback]); UseEffect () => {function tick() {savedcallback.current (); } if (delay ! == null) {// This is equivalent to a combination of setInterval and clearInterval applied to the component lifecycle. let id = setInterval(tick, delay); return () => clearInterval(id); } }, [delay]); }Copy the code

React Fiber

React renders components synchronously (” in one go “) from the start of setState to the end of rendering. If a large number of components need to be rendered, JS execution will occupy the main thread for a long time, resulting in poor responsiveness of the page and poor effect of React in animation, gesture and other applications.

The reason for Caton: Stack (the original algorithm) works much like a function call. The tone component in the parent component can be analogous to the recursion of a function. After setState, React will immediately start iterating from the parent node to find the difference. After all the Virtual DOM traversals are complete, information about the actual DOM that needs to be modified is given, passed to the Renderer, rendered, and the update is displayed on the screen. For very large vDOM trees, this process can take a long time (x00ms), during which the main thread is occupied by JS, so any interaction, layout, rendering stops, giving the user the impression that the page is stuck.

To solve this problem, the React team rewrote the core algorithm in React after two years of work. The new feature, called Fiber for short, was released in v16.

Fiber implements its own component call stack, which traverses the component tree in a linked list with the flexibility to pause, continue, and drop tasks. This is done using the browser’s requestIdleCallback API. Here’s the official explanation:

Window. RequestIdleCallback () will, in turn, calls the function in the browser free period, it can let developers performing background in the main event loop or low priority task, and not to delay trigger, such as animation and user interaction influence but the key event. Functions are generally executed in first-come-first-called order, unless the function reaches its timeout before the browser calls it.

Because the browser is single-threaded, it puts GUI rendering, timer handling, event handling, JS execution, and remote resource loading all together. When you do something, you have to finish it before you can do the next thing. If we have enough time, the browser will compile and optimize our code. Only by resting the browser well can it run faster.

The React to optimize

The code segment

  1. import()
  2. lazy + Suspense

The front-end optimization

SPA home page white screen optimization

Root cause

SPA applications are launched in a very similar way, providing a root node in HTML and mounting the application to that node.

This pattern, when packaged with Webpack, is usually three files:

  1. A small HTML that provides nothing but a root node (about 1-4 KB)
  2. A large js (ranging from 50 to 1000 KB)
  3. A CSS file (although if you put CSS into js, you may not have one)

As a direct result, the user’s page is completely blank before the JS file is loaded and executed. In other words, at this time

First screen Volume (volume of resources to load for first rendering) = HTML + JS + CSS

Optimize the way

  1. SSR(Server-side rendering)
  2. Prerender-spa-plugin (third-party plug-in)

We can use prerender-spa-plugin to add skeleton screens and Loading states to the project

Lazy loading

  1. Lazy loading of images
  2. Component lazy loading

Reduce the number of requests

  • Small image combined with Sprite image;
  • JS, CSS file selective merge;
  • Avoid duplicate resource requests.

Reduce file size

  • Compression CSS, JS, images;

  • Control DOM node number as much as possible;

  • Simplify CSS and JavaScript by removing comments, whitespace, repetitive CSS and scripts.

  • Open the Gzip

    } #footer {front-end learning training, video tutorial, learning route, add weixin kaixin666haoyun}