React vs Vue

Preface:

  1. There is no absolute right or wrong in technology selection
  2. There are many factors to consider in technology selection
  3. Express your opinion and give reasons

Essential differences between the two:

  1. Vue – EssentiallyThe MVVM framework, developed from MVC
  2. React – EssentiallyFront-end componentization framework, developed from back-end componentization
  3. But both do the same thing

The difference between templates:

  1. Ue – Using templates is proposed by Angular

  2. React – Uses JSX, a programming syntax similar to HTML

  3. Templates are syntactically more JSX oriented:

    • The instruction V – in vue needs to be learned now, and their values are in quotes, which is confusing;
    • In JSX, you just need to know that you can write JS expressions in braces, and that’s OK
  4. For template separation, vUE is preferred

Differences in componentization:

  1. React itself is componentization, and without componentization it would not be React
  2. Vue also supports componentization, but as an extension of MVVM
  3. For componentization, I prefer React, which is more thorough

What both have in common:

  1. Support for componentization
  2. Data-driven view

Conclusion:

1. In China, the first one is VUE. The documents are easy to read and learn, and the community is large enough

2. High team level, React, componentization and JSX are recommended

React

Understanding of componentization

Similar to object-oriented, it is divided into: encapsulation, inheritance, polymorphism

Encapsulation of components

  1. view
  2. data
  3. Change logic (data-driven view change)

After the assembly is complete, the user does not need to understand the view, data, and change logic of the component, and only needs to provide the data required by the component

Component reuse

  1. Props (passing different data makes different effects for the component, but the template is the same)
  2. reuse

The essence of the JSX

A programming syntax introduced by React, similar to HTML

JSX grammar

JSX syntax cannot be parsed directly by the browser and ultimately needs to be converted to JS to run

  1. HTML (normal tags)
  2. Introduce JS variables and expressions
  3. If judgment
  4. The for loop
  5. Style and calssName
  6. event

JSX Parsing (essence)

JSX is syntax sugar that needs to be parsed into JS to run, via React. CreateElement (‘tagName’, {tag attribute}, child element…) Can be associated with the H function in VDOM (generating vNode)

  1. JSX is actually syntactic sugar
  2. The development environment compiles JSX into JS code
  3. The writing method of JSX greatly reduces the learning cost and coding workload

JSX has been standardized

  1. JSX was introduced by React, but is not unique to React
  2. Other JSX projects can also be used
  3. React. CreateElement is customizable
  4. Note: Its functions have been complete, compatibility and scalability is no problem

Relationship between JSX and VDOM

Why do YOU need vDOM

  1. Vdom was first popularized by React and used in conjunction with JSX
  2. JSX is a template (similar to the VUE template) that ultimately needs to be rendered into HTML
  3. Initial render + re-render after changing state
  4. It fits the application scenario of VDOM

The React. CreateElement () and h() functions

All JSX code is parsed into JS code for execution, which returns VNode

When the patch

  1. First render – reactdom.render (, container), will trigger patch(Container, vnode)
  2. Re-render-setstate triggers patch(vNode, newVnode) comparison

Processing of custom components

  1. ‘div’ will render directly to<div>
  2. Input and List are custom component classes, which vDOM does not recognize by default
  3. Therefore, the render function must be declared when Input and List are defined
  4. Initialize the instance with props and dye back the render function that executes the instance
  5. The render function returns a VNode object
return React.createElement('div'.null, 
  React.createElement(Input, {addTitle: this.addTitle.bind(this)}),
  React.createElement(List, {data: this.state.list}),
  React.createElement('p'.null.'this is demo'))// React. CreateElement (List, {data: this.state.list})
const list = new List({data: this.state.list})
const vnode = list.render()
Copy the code

conclusion

  • Why vDOM is needed:

JSX needs to render HTML, and render HTML through VDOM data-driven view manipulation

  • React. CreateElement, like the h function, generates vNode
  • When patch: reactdom.render () first render and setState subsequent update
  • Custom component parsing: initialize the instance and then execute the render function to return vNode

React lifecycle

Mounting stage

The Mounting phase is called the Mounting phase. Along with the generation of the entire virtual DOM, there are three life cycle functions in it, which are:

  1. ComponentWillMount: Executed before the component is mounted to the page
  2. Render: executed when page initialization, state, and props change
  3. ComponentDidMount: Executed when the component is mounted
componentWillMount:

This function is executed only once, when the component is initialized or when the page is refreshed.

render:

Render () is a pure function that returns only what needs to be rendered. It should not include any other business logic. It can return native DOM, React components, fragments, strings, numbers, Boolean, and null.

componentDidMount:

This function is executed only once, when the component is initialized or when the page is refreshed.

After the component is loaded, you can get the DOM node and operation, such as canvas, SVG operation, server request, subscription can be written in it, but remember to unsubscribe in componentWillUnmount

The Updation is the update phase

The Updation phase is also the update phase in which components change. It consists of two basic parts: the props attribute changes and the state state changes

  1. ShouldComponentUpdate: Executed automatically before the component is updated
  2. ComponentWillUpdate: Executed after the function shouldComponentUpdate returns true
  3. render()
  4. ComponentDidUpdate: Executed after a component update. This is the last step in the component update
shouldComponentUpdate:

ShouldComponentUpdate (nextProps, nextState), which takes two arguments, nextProps and nextState, to indicate the new property and the changed state, returns a Boolean value, true means that rerendering will be fired, False means that rerendering will not be triggered and returns true by default. This lifecycle is often used to optimize React program performance

render

This function is also triggered during the update phase

componentDidUpdate:

ComponentDidUpdate (preProps, preState, snapshot). This method takes three parameters. It is executed after the previous props, state, and snapshot components are updated

Unmounting Uninstallation phase

  1. ComponentWillUnmount: called when our component is unmounted or destroyed
componentWillUnmount:

Garbage cleaning can be performed in functions before the component is destroyed, removing timers, canceling network requests, cleaning up invalid DOM elements, and so on

Life cycle improves program performance

Improve React component performance with shouldComponentUpdate
// nextProps: properties after the change, nextState: state after the change
shouldComponentUpdate(nextProps, nextState) {
    if(nextProps.content ! = =this.props.content) {
        return true
    }else {
        return false}}Copy the code

Vue

The navigation hook for vue-router

Global guard

BeforeEach Global front guard

Receive three parameters:

  • To: Route: indicates the destination Route to be entered
  • From: Route: Indicates the Route that the current navigation is leaving
  • Next: Function: Be sure to call this method to resolve the hook
router.beforeEach((to, from ,next) = > {
    if(to.name ! = ='Login' && !isAuthenticated) {
        next({name: "Login"})}else {
        next()
    }
})
Copy the code
AfterEach Global afterhook

This hook does not accept the next function, nor does it change the navigation itself

router.afterEach((to, from) = > {
    // ...
})
Copy the code

Route exclusive guard

BeforeEnter guards can be defined directly on the route configuration

const router = new Router({
    routes: [{path: '/foo'.component: Foo,
            beforeEnter: (to, from , next) = > {
                // ...}}}])Copy the code

A guard inside a component

beforeRouteEnter
  1. Called before the rendering component’s corresponding route is confirmed
  2. Cannot get component instance this
  3. The component instance has not been created before the guard executes
  4. A component instance can be accessed by passing a callback to Next
beforeRouteEnter(to, from , next) {
    next(vm= > {
        // Access the component instance through the VM})}Copy the code
beforeRouteUpdate
  1. Called when the current route has changed, but the component is being reused
  2. For a path with dynamic parameters /foo/:id, jump between /foo/1 and /foo/2
  3. Since the same Foo component is rendered, component instances are reused. The hook will be called in that case
  4. Component instances can be accessedthis
beforeRouteUpdate(to, from , next) {
    // just use this
    this.name = to.params.name
    next()
}
Copy the code
beforeRouteLeave
  1. When navigating away from the corresponding route of the component
  2. Component instances can be accessedthis
beforeRouteLeave(to, from ,next) {
    const answer = window.confirm('Do you realy want to leave? ')
    if(answer) {
        next()
    }else {
        next(false)}}Copy the code

Vue-router indicates the hash mode and history mode

In vue’s routing configuration, there is a mode option. The most obvious difference is that the hash url has a # character, while the history url does not. By default, vue uses the hash mode

const router = new VueRouter({
    mode: 'history'.routes: [{path: ' '.name:' '.component:... }]})Copy the code

The front-end routing

Hash:

Use the hash (#) in the URL as the route, and listen for the hash changes to find the content in the corresponding component to update to the page; Support for all browsers

History:

Use the HTML5 History API and server configuration; Refer to the HTML5 History mode on the official website. Compatibility, support for specific browsers

The back-end routing

  • Access the URL directly and request resources from the server

The difference between the front and rear ends

  • The back-end route sends a request to the server
  • The front-end route does not send a request to the server when modifying the view

Implementation and distinction of hash mode and History mode

Front-end routing implements two functions from the user’s perspective (in the case of updating page state with Ajax)

  1. Record the state of the current page (save and share the url of the current page, and open the URL again, the page is still the state of the saved share)
  2. Instead, use the browser’s forward and back functions (e.g. clicking the back button can return the page to the state before the Ajax update, and the URL page to the previous state).

As developers, to implement these two features, we need to:

  1. Monitor url changes
  2. Change the URL and prevent the browser from making requests to the server
  3. It intercepts URLS and parses the required information to match routing rules

Note: Our front-end routing commonly used hash mode and history mode, in fact, to achieve the above function

Hash pattern

The hash is the hash at the end of the URL and the character after it; The # here is the same as the # in CSS; Hashes, also known as anchors, are used for page positioning and can be displayed in the visual area using the corresponding ID element.

Until HTML5 history came along, people used hashes for front-end routing because hash changes don’t cause the browser to make a request to the server, and because hash changes trigger hashChange events that the browser can control when it moves forward or backward

Features:

  • Good compatibility, all browsers are supported
  • Although the hash appears in the URL, it is not included in the HTTP request and has no effect on the backend, so changing the hash does not reload the page
  • Hashes are used for page positioning. If they are used for routing, the original anchor function is disabled
  • The hash parameter is URL-based and has a volume limit if you want to pass complex data

The core API:

  • The onHashChange event: triggered when the anchor part of the current URL (starting with #) changes. Hash changes include the following parts
  1. Manually changing the URL
  2. Manually modify the Hash
  3. Browser forward and backward

Vue implements hash routing as follows:

<p>hash test</p>
<button id="btn">Modify the hash</button>
<script>
    window.onhashchange = (event) = > {
        console.log('old url', event.oldURL)
        console.log('new url', event.newURL)
        console.log('hash', location.hash)
    }
    // The home page is loaded for the first time to obtain the hash
    document.addEventListener('DOMContentLoaded'.() = > {
        console.log('hash', location.hash)
    })
    // js modifies the URL
    document.getElementById('btn').addEventListener('click'.() = > {
        location.href = "#/user"
    })
</script>
Copy the code

The history mode

The History pattern can not only put parameters in the URL, but also put data in a specific object.

History takes advantage of the new pushState() and replaceState() methods in the HTML5 History Interface; (Requires browser-specific support) History does not work below IE8

Features:

  • Compatible with specified browsers
  • Without the symbol #, it looks much more elegant
  • PushState () adds any type of data to a record with the stateObject parameter

The core API:

  • PushState (state, title, URL) : a new HTML5 interface that pushes data into the session history stack by the specified name and URL (if provided). The url can be changed (with cross-domain restrictions) without refreshing the page

    • State is a JavaScript object that pushes State () to create a new history entry
    • Title: Title – Firefox currently ignores this parameter, but may use it in the future
    • Url: This parameter defines a new historical URL record
  • History.replacestate (State, title, URL) : HTML5 new interface, according to the specified data, name and URL(if provided), modify the latest entry on the history stack, can change the URL(there are cross-domain restrictions) without refreshing the page

    • State, title, and URL are the same as pushState
  • Window. onPopState: is the event handler for popState events on the Window object

    • Calling history.pushState() or history.replacestate () does not raise the popState event
    • Popstate events are only triggered by certain browser actions, such as clickingBack and forward buttons(or in JavaScriptHistory.back (), history.forward(), history.go()Methods), in addition,The anchor point of the A tag also triggers the event
window.onpopstate = function(event) {
  alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
// Bind the event handler
history.pushState({page: 1}, "title 1"."? page=1");
/ / add and activate a history entry http://example.com/example.html?page=1, entry index of 1
history.pushState({page: 2}, "title 2"."? page=2");
/ / add and activate a history entry http://example.com/example.html?page=2, entry index of 2
history.replaceState({page: 3}, "title 3"."? page=3");
// Modify the currently active history entry http://ex.. ? Page = 2 to http://ex.. ? Page =3, entry index 3

history.back();
/ / the pop-up "location: http://example.com/example.html?page=1, state: {" page" : 1}"
history.back();
/ / the pop-up "location: http://example.com/example.html, state: null
history.go(2);
/ / the pop-up "location: http://example.com/example.html?page=3, state: {3}" page ":
Copy the code

Vue implements the principle of history routing:

<p>H5 history</p>
<button id="btn">Modify the</button>
<script>
    // The home page is loaded for the first time and the path is obtained
    document.addEventListener('DOMContentLoaded'.() = > {
        console.log(location.pathname)
    })
    // Open a new route
    // [Note] With pushState, the browser does not refresh the page
    The history.pushState() method adds a state to the browser history
    // pushSteate() takes three arguments: the state object, the title (currently ignored), and the URL
    document.getElementById('btn').addEventListener('click'.() = > {
        const state = {
            name: 'page1'
        }
        console.log('Switch routing to'.'page1')
        history.pushState(state, ' '.'page1') // pushState ***
    })
    // Listen to the browser forward and backward onPopState
    window.onpopstate = (event) = > { //onpopstate *** 
        console.log('onpopstate', event.state, location.pathname)
    }
</script>
Copy the code

conclusion

The hash mode and history mode are features of the browser. Vue-router only uses these two features (by calling the interface provided by the browser) to implement front-end routing, such as registering the VUE global plug-in and registering the VUE global component (router-view)

The difference between:

  • Hash through the window.onhashchangeListen for hash changes
  • H5 History adds/modifies a record to the browser history via history.pushState()/replaceState(), via window.onpopstateListen to the browser go forward or backward
  • H5 History requires simple routing configuration on the back end (Apache or Nginx), coupled with front-end routing support for 404 pages

Trade-off:

  • To B system recommends the hash, which is easy To use and insensitive To URL specifications
  • To C system, H5 history can be considered, but needs server-side support

basis

base

  1. Web standards

    • Structure: Web standardization technologies for structure are mainly Html, Xhtml, and Xml
    • Presentation: Mainly CSS
    • Behavior: The main standard techniques for representing behavior are Dom and Javascript
  2. Major browsers and kernels

    • Chrome – Blink
    • Safari – Webkit
    • Firefox – Gecko
    • IE – Trident
    • Opera – Blink
    • Baidu, Window of the world – IE kernel
    • 360, Cheetah browser – IE+Chrome dual core
    • Sogou, QQ browser – Trident(compatible mode)+Webkit(high-speed mode)

HTML

The role of the DOCTYPE

DOCTYPE is a standard HTML5 web page declaration and must be declared in the first line of an HTML document
. It tells the browser’s parser what document standards to use to parse this document

The document parsing types are:
  • BackCompat: Weird mode, which is used by default
    • Emulates the behavior of older browsers
  • CSS1Compat: In standard mode, browsers use W3C standards to parse rendered pages
    • The page is rendered as defined in HTML and CSS

The difference between HTML, XHTML, and XML

  • HTML(HyperText Markup Language): Prior to HTML4.0, existing implementations of HTML had standards, resulting in HTML being very messy and loose
  • XML(Extensible Markup Language): Used primarily for storing data and structures, extensible and similar to JSON
  • XHTML(Extensible HyperText Markup Language): Based on the above two, the W3C was born to solve the HTML mess, based on which HTML5 was born, added first<! DOCTYPE html>Is the standard model

HTML semantic understanding

Semantic is the use of appropriate HTML tags so that the page has good structure and meaning, such as

for paragraphs,

for body content, etc.
Benefits of semantics:
  • Developer friendly: Use semantic class tags to enhance readability. Developers can see the structure of the web page clearly, which is easier for team development and maintenance
  • Machine friendly: semantic class tags, more suitable for search engine crawlers to crawl effective information
  • It is very important for rich text applications such as Zhihu and Nuggets, and semantic is of great help to the content dissemination of their websites

Meta tags

Meta tags are defined by the name and content attributes, which describe the attributes of an HTML page document, such as author, time, description, keywords, page refresh, etc. In addition to some names specified in HTTP, developers can also customize names

  • Charset: Describes the encoding form of an HTML document
    <meta charset="UTF-8" >
    Copy the code
  • Http-equiv: is equivalent to the HTTP header. You can set the HTTP cache expiration date as follows
    <meta http-equiv="expires" content="Wed, 20 Jun 2019 22:33:00 GMT" >
    Copy the code
  • Viewport: In mobile, developers can control the size and proportion of the viewport
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" >
    Copy the code
  • Apple-mobile-web-app-status-bar-style: Familiar to developers who have developed PWA applications, in order to customize the color of the evaluation toolbar
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" >
    Copy the code

The difference between SRC and href

  • SRC refers to the location of external resources. The content pointed to will be embedded in the location of the current tag in the document. When requesting SRC resources, the resources pointed to will be downloaded and applied to the document, such as JS script, IMG image, frame and other elements. When the browser parses this element, it suspends the downloading and processing of other resources until the resource is loaded, compiled, and executed, so the JS script is usually placed at the bottom rather than the head
  • Href is the location of the network resource (hyperlink), used to establish a connection to the current element, document, when the browser recognizes the file it is pointing to, will download resources in parallel, will not stop processing the current document

The role of srcset in img

Srcset provides the ability to select images based on screen conditions

To design responsive images, we can use two new properties srcset and SIZES to provide additional resource images and tips to help the browser select the right resource. Srcset defines the set of images we allow the browser to select, and the size of each image. Sizes defines a set of media conditions (such as screen width) and specifies what image size is the best choice when certain media conditions are true.

With the above attributes, the browser will:

  • Viewing device Width
  • Check the sizes list for which media condition is the first true
  • View the slot size given to the media query
  • Loads the image closest to the selected slot size referenced in the SRcset list
    <img 
        src="clock-demo-thumb-200.png"
        alt="clock"
        srcset="clock-demo-thumb-200.png 200w, clock-demo-thumb-400.png 400w"
        sizes="(min-width:600px) 200px, 50vw" />
    Copy the code

The difference between defer and async in the script tag

  • defer: <script defer>The browser instructs the script to be executed after the document is parsed. The script is asynchronously loaded and does not execute immediately, but waits until the document is parsed
  • acync: <script async>The same is true for asynchronous loading, but the difference is that the script is executed immediately after it is loaded. This causes the scripts under the async property to be out of order, which is not applicable to the situation where script dependencies are sequential
  • Bottom line: Defer is to load asynchronously and wait until the document is parsed before executing; Async is also loaded asynchronously and is executed immediately after loading. Script is usually placed at the end of the document in a project

Front-end storage

  • Cookies: The primary form of local storage prior to HTML5

    • Advantages: Good compatibility, request header built-in cookies convenient
    • Disadvantages: small size only 4K capacity, each request to bring cookies overall waste of traffic
  • LocalStorage: HTML5 added to the key value pair (key:value) as the standard storage method

    • Advantages: Easy to operate, permanent storage (5M), compatible with IE8+
  • SessionStorage: Similar to the preceding, except that sessionStorage is cleaned up after the page is closed. Different from cookies and localStorage, sessionStorage cannot be shared in all same-source Windows and is a session-level storage mode

  • IndexedDB: Officially incorporated into the HTML5 standard for database storage, IndexedDB is a NoSQL database that uses key-value pairs for storage and can be read quickly, making it ideal for Web scenarios

HTML 5 new features

New semantic, structured tags

The label The label
<article> : Defines the article content in the document <aside> : Sidebar
<header> <footer>
<main> The < nav > : navigation
<section> : Defines a section in a document, similar to div

The way a box is centered horizontally and vertically

// HTML section (this section is unchanged, the following examples are shared)<body>
  <div id='container'>
    <div id='center' style="width:100px; height:100px; background-color: #0F0">center</div>
  </div>
</body>
Copy the code

1. Absolute positioning + negative margin realization (known box width and height)

  • Note: This method needs to know the width and height of the centered element in order to calculate margin, which is compatible with all browsers
// css
#container {
    position: relative;
}
#center {
    position: absolute;
    top: %50;
    left: %50;
    margin: -50px 0 0 -50px;
}
Copy the code

2. Absolute positioning + margin: auto;

  • This method does not need to know the width and height of the vertically centered element and is not compatible with earlier browsers
#container {
    position: relative;
    height: 100px; // Must declare height}#center {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}
Copy the code

3. Absolute positioning + CSS3 (unknown element height)

  • Using CSS3’s transform, the vertical center of the element can be realized when the width and height of the element are unknown
#container {
    position: relative;
}
#center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
Copy the code

4. The flex layout

  • The Flex layout, in which justify-content and align-items are aligned, is not compatible with earlier Versions of Internet Explorer.
// Set it directly in the parent container#container {
    height: 100px; // Must have heightdisplay: flex;
    justify-content: center;
    align-items: center;
}
Copy the code

5.flex/grid + margin: auto; (Simplest writing)

  • If the container element is set to a Flex or grid layout, just write margin: auto for the child element; Yes, it is not compatible with Internet Explorer of earlier versions.
#container {
    height: 100px; // Must have heightdisplay: flex/grid;
}
#center {
    margin: auto;
}
Copy the code

CSS

The priority of the CSS selector

The priority of CSS selectors is: Inline style >ID selector > Class selector > Tag Selector

  • Inline – 1.0.0.0
  • ID selector – 0.1.0.0
  • Class selector -0.0.1.0
  • Tag selector -0.0.0.1

Selectors of the same type add but do not carry

The difference between link and @import

  • Link belongs to the XHTML tag, and @import is provided by CSS
  • While the link is loaded at the same time as the page is loaded, the CSS referenced by @import is not loaded until after the page is loaded
  • Import is only recognized in IE5, while link is an XHTML tag and has no compatibility issues
  • The link style weight is higher than the @import weight

Hide page elements (CSS)

  • opacity: 0; The essence is to make the elements transparent, still occupying space and interacting
  • visibility: hidden; Elements are hidden, occupy space, and cannot interact
  • overflow: hidden; Hide only the overflow parts of the element, occupy space, and are not interactive
  • display: none; Removing elements from the document stream without occupying space or interacting
  • z-index: -9999; The idea is to place the element hierarchy at the lowest level, overlaid by other elements
  • The transform: scale (0, 0); The element is scaled to zero, occupies space, and cannot interact
  • transform: translate(-1000px); Moves an element out of view

The difference between p/em/rem

  • Px: An absolute unit, displaying the page in exact pixels
  • Em: the relative unit. The reference point is the font size of the parent element. If the font size is defined by itself, the 1em is not a fixed value for the entire page
  • Rem: a relative unit. The reference point is always the FONT size in HTML. 1REM for the entire page is a fixed value

Z – the understanding of the index

Control sets the vertical overlay order of the elements with the position attribute. The default value of the element is 0. Change the z-index to control the layer position of the elements

  • .
  • Layer 2
  • 1 layer
  • Layer 0, default
  • 1 layer
  • – 2 layer
  • -…

Cascading context

Definition:

Is a three-dimensional concept of an HTML element, an imaginary extension of the Z-axis relative to a computer screen or a web page. HTML elements take up space in the cascading context according to their own attributes in order of priority

Produce:
  • The value of Z-index is not relative, Absolute and fixed of auto
  • Elements whose value is less than 1
  • Elements whose transform attribute value is not None

Method to clear the float

  • Add extra label -clear: both;
    <div>
        // ...
        <div style="clear: both;"></div>
    </div>
    Copy the code
  • Parent adds overflow property (BFC) or sets height
    <div style="overflow: hidden;">
        // ...
    </div>
    Copy the code
  • Clear float for class selectors (recommended)
    .box:after {
        content: '';
        display: block;
        height: 0;
        visibility: hidden;
        clear: both;
    }
    <div class="box">
        // ...
    </div>
    Copy the code

Understanding of the box model

The box model is composed of content, padding, border and margin

Definition:

When a document is laid out, the browser’s rendering engine represents all the elements as rectangular boxes according to one of the standard CSS base box models. CSS determines the size, position, and properties of these boxes (color, background, border, and so on)

The difference between standard box model and weird box model

Standard box model

Width === content, height === content, so the width of the element is:

Width = margin-left+margin-right+border-left+border+right+padding-left+padding-right+width

Weird box model

In IE weird box model (IE8 below)width! Width === border-left+border-right+padding-left+padding-right+width

Width = margin-left+margin-right+width

Change box model
box-sizing: content-box; // Box-sizing: border-box; // Weird box modelCopy the code

The understanding of the landing

Block-level format context: It is a separate area that separates elements inside the BFC from those outside

The trigger condition
  • The root element, the HTML element
  • position: fixed/absolute;
  • Float to none
  • Voerflow visible
  • The display value is inline-block, table-cell, and table-caption
Application scenarios
  • Prevent float resulting in parent element height collapse
    <style>
     .container {
        border: 10px solid red;
        overflow: hidden;
    }
     .inner {
        float: left;
        background: #08BDEB;
        height: 100px;
        width: 100px;
    }
    </style>
    <div class="container">
        <div class="inner">
            // ...
        </div>
    </div>
    Copy the code
  • Avoid margin folding
    <style>
     .container {
        background-color: green;
        overflow: hidden;
     }
     .inner {
      background-color: lightblue;
      margin: 10px 0;
     }
     .bfc{
      overflow: hidden;
     }
    </style>
    <div class="container">
    <div class="inner">1</div>
    <div class="bfc">
      <div class="inner">2</div>
    </div>
    <div class="inner">3</div>
    </div>
    Copy the code

Translate and position change the difference between the position of an element

  1. Translate is a value of transform, and changing transform or opacity does not trigger a browser reflow or repaint
  2. Changing absolute positioning triggers a browser relayout, which in turn triggers a redraw
  3. Transform causes the browser to create a GUP layer for the element, but changing the absolute positioning uses CPU
  4. Use Translate to be more efficient and reduce the drawing time for parquet animations

The difference between pseudo-classes and pseudo-elements

Pseudo-class: keyword prefixed with colon: that is added to the end of a selector. When you want the style to be rendered to an element in a particular state, you can add the corresponding pseudo-class after the element’s selector

  • Elements: first – child {}
  • Elements: the NTH – child (n) {}
  • Chemical element: hover {}
  • Chemical element: focus {}
  • A :link {unvisited link}
  • A: I visited the park yesterday.
  • A :active {selected link}

Pseudo-elements: Used to create and style elements that are not in the document

  • ::before
  • ::after
The difference between
  • A pseudo-class changes the state of an element by adding a pseudo-class to the element selector
  • A pseudo-element is an element added by an operation on the element

Less

Less preprocessor: Supports CSS syntax, introducing variables, mixing, computing, nesting, etc., simplifying CSS writing and reducing maintenance costs

variable
  • Syntax: @ variable name: value;
    @sz: 1000px;
    p {
        font-size: @sz;
        span {
            / / operation
            font-size: @sz - 2; }}Copy the code
nested
```less .box { background-color: #0f0; ul { list-style: none; }} ` ` `Copy the code
Mix (function)
  1. Definition: # function () {} | |. The function name () {}
  2. Call: # function name | |. The function name
  3. Pass parameters, default values
    / / 1. Definitions
    #public() {
        width: 200px;
        height: 200px;
    }
    .origin() {
        width: 200px;
        height: 200px;
    }
    / / 2. Call
    div {
        #public()}h2 {
        .public()}// 3. Pass parameters and default values
    #base(@w:200px.@h:200px) {
        width: @w;
        height: @h;
    }
    div {
        #base(600px.600px);
    }
Copy the code

Sass

variable
  • Syntax: $blue: #1875e7;
$blue: #1875e7;
div {
    color: $blue;
}
Copy the code
  • Nested in a string, must be written in# {}In the
$side: left;
.rounded {
    border-#{$side}-radius: 5px;
}
Copy the code
Computing functions
body {
    
}
Copy the code

JS

JS based

Talk about your understanding of prototype chains

The key to this problem lies in two points: prototype object and prototype chain formation

  • A prototype object

    • Most functions have a prototype property that points to the prototype object. All objects created by the same function can point to the prototype object through its own __proto__ property, so that objects can access the prototype’s properties through __proto__

    • For example, the hasOwnProperty() method exists in the Object prototype, so it can be used by any Object as its own method

    <script>
        // Constructor only methods in the stereotype can also hold properties for calls to objects of the same class.
        // Equivalent to the prototype method shared to the same class of objects, saving memory
        function Students(name, age) {
            this.name = name;
            this.age = age;
        }
        // Find the prototype
        var yxStudents = Students.prototype;
        // Add methods to the prototype
        yxStudents.sayHi = function (swing, code) {
            // This in the method refers to the caller of the method
            console.log('my name is'+this.name+This year, ' '+this.age+'My favorite thing is'+swing+', my major is'+code+'Programmer');
            return this;
        };
        yxStudents.type = 'students';

        var stu1 = new Students(Small five ' '.18);
        stu1.sayHi('swimming'.'Java');
        console.log(stu1);
        // The instance object __proto__ contains the address of the prototype object
        
        console.log(stu1.__proto__ === yxStudents);
        // How are objects in the instance shared with members in the stereotype
            // If the instance object is not found,
            // The prototypeobject will be found using the prototypeaddress provided in the __proto__ assigned by the system
            // If not, look in the prototype of the prototype


    </script>
Copy the code
    obj.hasOwnProperty(key)
    // Return true if object obj contains the key attribute, otherwise false
Copy the code
  • Prototype chain

    • The reason is that every object has a __proto__ attribute, which points to the prototype of the object’s constructor
    • Objects can be linked by __proto__ to the upstream constructor’s prototype object, which also has a __proto__, thus forming a prototype chain

Determines whether a variable is an array

  • Array.isArray(arr)

    if(Array.isArray(value)) { return true }
    Copy the code
  • toString(arr)

    if(!Array.isArray) {
        Array.isArray = function(args) {
            return Object.prototype.toString.call(args) === "[object Array]"}}Copy the code

ES6 module and CommonJS module difference

  • ES6 Module and CommonJS Module
  1. CommonJS is a shallow copy of a Module. ES6 Module is a reference to a Module. That is, ES6 Module is read-only and cannot be changed
  2. The import interface is read-only and cannot be modified. That is, you can’t change the pointer to the variable, but you can change the internal pointer to the variable; CommonJS can be reassigned (changing the pointer to it), but an ES6 Module assignment will compile an error
  • What ES6 Module and CommonJS Module have in common:
  1. Both CommonJS and ES6 Modules can assign values to imported objects, that is, change the internal properties of the object

async/await

Async functions, the syntax-sugar of Generator functions, are built on Promises and are compatible with all Promise-based and API’s

  1. Async Declares an asynchronous function
  2. Automatically converts a regular function to a Promise, returning a Promise object
  3. The callback function specified by the THEN method is executed only after the asynchronous operation within the async function has completed
  4. Async functions can use await inside

Await suspends asynchronous function execution

  1. Placed before a Promise call, the await forces subsequent code to wait until the Promise completes and returns the result
  2. Use only with Promises and not for callbacks
  3. Can only be used inside async functions

The advantages of async/await over promises

  • The code is similar to synchronous code, and promises get rid of callback hell, but chaining calls to.then also imposes an extra reading burden
  • Promises are cumbersome to pass intermediate values, while async/await is written almost synchronously
  • Error handling is more friendly, async/await uses try/catch,Promise uses.catch is very redundant
  • Debugging is friendlier. After a debugger is used in a.THEN, the debugger cannot access subsequent blocks of.THEN code because the debugger can only track synchronous code

How JavaScript parameters are passed

  • Basic type passing mode

    Primitive type data in JS is passed by value

    var a = 1
    function test(x) {
        x = 10
        console.log(x)
    }
    test(a) / / 10
    console.log(a) / / 1
    Copy the code
  • Complex types are passed by reference

    function test(person) {
        person.age = 26;
        person = {
            name: 'ijk'.age: 123
        }
        return person
    }
    const p1 = {name: 'xyz'.age: 20}
    const p2 = test(p1)
    console.log(p1) // {name: 'xyz', age: 26}
    console.log(p2) // {name: 'ijk', age: 123}
    Copy the code
  • Pass by share

    The reason for this feature of complex types is that, in the process of passing, object P1 produces a copy p1, which is not the deep-cloned copy P1, and the address of the copy P1 also points to the heap memory that object P1 points to.

    Therefore, changing Person in the function only changes the copy p1, and p1 object does not change, but changing person.age = 26 changes the same heap memory that both point to, and p1 is also affected.

    This feature is called passing references or passing by share.

BingInt proposal

MAX_SAFE_INTEGER === 2^56, that is, there is no precision loss in the range of this Number (except decimals). However, once this range is exceeded, inaccurate computation will occur in JS, making it necessary to rely on third-party libraries to solve the problem when calculating large numbers. Therefore, BinInt is officially proposed to solve the problem.Copy the code

Difference between null and undefined

An object can be null, representing an empty object, and NULL itself is not an object, because the beginning of 000 represents an object, and null is all zero, so it is misinterpreted as an object. Undefined means that there is no object. JS is a dynamic typing language, members in addition to representing the value of existence, Or it might not exist at all (because it's only known at runtime), which is where undefined is all about.Copy the code

Rules for type conversion

Turn the string

  • Any data added to a String is automatically converted to String first
    console.log('1'+NaN) // 1NaN
    console.log('1'+1) / / 11
    console.log('1'+false.'1'+true) // 1false 1true
    console.log('1'+undefined) // 1undefined
    Copy the code

Turn to digital

  • Any data is automatically converted to type Number first when it is used for arithmetic (other than adding to a string) or when it is compared to a Number
  • Any data computed with NaN (except when added to a string) will always result in NaN
    console.log(1-'1') / / 0
    console.log(1+true) / / 2
    console.log(1-'a') // NaN
    console.log(1+undefined) // NaN
    Copy the code

Turn the Boolean

  • The other data is automatically converted to a Boolean value when the operation is reversed
  • Other data is automatically converted to a Boolean value in a branching or loop condition

‘1’. The toString () call

During the execution of this statement, the following things are done:

// 1. Create an instance of String class
var s = new String('1')
// 2. Call the instance method
s.toString()
// 3. Destroy the instance immediately after executing the method
s = null
Copy the code

The whole process reflects the nature of the basic wrapper types, which belong to the basic data types, including Boolean, Number, and String.

0.1 + 0.2! = = 0.3?

The Number type of JS follows the IEEE754 standard and uses a fixed length of 64 bits.

0.1 and 0.2 will enter an infinite loop after being converted to binary. Due to the limit of standard bits, the excess bits will be cut off, and the accuracy will be lost. After being added, the truncated binary digits due to the limit of decimal digits of floating point numbers will be lost when being converted to decimal.

JS mechanism

Variable ascension

The way the JS engine works is that it first parses the code, gets all the declared variables, and then runs them line by line. As a result, all variable declarations are promoted to the top of the code. This is called variable promotion.

console.log(a) // undefined
var a = 1
function b() {
    console.log(a)
}
b() / / 1
Copy the code

Var a = undefined; var a = undefined; a = undefined; var a = undefined;

var a = undefined; // Variable promotion
console.log(a) // undefined
a = 1;
function b() {
    console.log(a)
}
b() / / 1
Copy the code

Step 2: So the JS engine executes line by line from top to bottom to produce the current result, which is called variable promotion.

JS scope chain

JS belongs to static scope, that is, the scope of the declaration is determined according to the body of the program at compile time, sometimes called this scope.

Its essence is that JS will create executable context in the execution process, and the lexical environment of the executable context contains a reference to the external lexical environment. We can obtain variables and declarations of the external lexical environment through this reference. These references are connected in series and always point to the global lexical environment, thus forming a scope chain.

This of the arrow function

Unlike traditional JS functions, the arrow function does not have its own “this”. Its so-called “this” is to capture the value of this in its context as its own “this”. The arrow function is not called by new, and the so-called “this” is not changed.

We can use Babel to understand the arrow function:

// ES6
const obj = {
    getArrow() {
        return () = > {
            console.log(this === obj)
        }
    }
}
Copy the code

After the transformation

// ES5, translated by Babel
var obj = {
    getArrow: function getArrow() {
        var _this = this;
        return function() {
            console.log(_this === obj)
        }
    }
}
Copy the code

ES6

Block-level scope

  • Those wrapped in {} represent block-level scope
for(let i=1; i < 3; i++) {
    console.log(i) / / 1. 2
}
// console.log(i) // ReferenceError: i is not defined
// ES6 forces strict mode 'use script', variables cannot be referenced if not declared, ReferenceError
Copy the code

let

  • Variables are valid only in their own block-level scope
  • Declared variables cannot be defined repeatedly
let a = 1
let a = 2 . / / the ERROR in/app/js/class/lesson1.1. Js
Copy the code

const

  • Declared constants cannot be modified and are only valid within their own block-level scope
  • A value must be assigned when declared
  • When a declared constant is of a reference type, you can change the value of the data inside the reference type
  const PI = 3.1415926
  const k = {
    a: 1
  }
  k.b = 2
  // PI = 2 // ERROR
  console.log(PI,k)
Copy the code

Deconstruction assignment

The basic use

// Assign variables
let a,b
[a,b] = [1.2]
// console.log(a,b) // 1 2
Copy the code

Array destruct assignment

/ /... An important feature of deconstructing assignments
[a,b,...rest] = [1.2.3.4.5.6.7.8]
// console.log(a,b,rest) // 1 2 (6) [3, 4, 5, 6, 7, 8]

/ / the default value
let a,b,c
[a,b,c=3] = [1.2]
console.log(a,b,c) / / 1 2 3

// Change variables
let a = 1;
let b = 2;
[a,b] = [b,a] // console.log(a,b) // 2 1

Copy the code

Object to destruct assignment

/ / the default value
let {a = 10, b = 5} = {a:3} // console.log(a,b) 3 5

/ / names
let metaData = {
    title: 'abc'.test: [{
      title: 'test'.desc: 'description'}}]let {title:esTitle,test: [{title:cnTitle}]} = metaData
console.log(esTitle,cnTitle) // abc test
Copy the code

Arrow function

  • The this object in the body of the function is the object that was defined, not the object that was used
  • It cannot be used as a constructor, that is, it cannot use the new command
  • Do not use the Arguments object. It does not exist in the function body
  • You cannot use the yield command, so arrow functions cannot be used as Generator functions

modular

/ / export
// utils1.js
export default {
  a: 1
}
// utils2.js
export function fn1() {
  console.log('fn1')}export function fn2() {
  console.log('fn2')}/ / introduction
import utils1 from './utils1.js'
// export ... export ... - > import {... }
import {fn1, fn2} from './utils2.js'
console.log(utils1)
fn1()
fn2()
Copy the code

Promise

Promise is a new solution for asynchronous programming in JS (the old one was pure callback)

Promise’s status changed
  • Pending to resolved
  • Pending a rejected

Note: Only the above two changes, and a promise object can be changed only once, whether it becomes a success or failure, there will be a result data, the successful result data is called RES, the failure of the result data is called rej

Promise’s basic process
  1. Resolve () -> Promise(pending status) -> resolve() -> Promise(resolved status) -> call back onResolved() (then()) -> new Promise
  2. New Promise() (pending state) -> reject() -> Promise object (rejected state) -> callback onRejected() (then()/catch()) -> new Promise object
Promise’s basic use
const pm = new Promise((resolve, reject) = > {
    setTimeout(() = > {
        const time = Date().now()
        if (time % 2= = =0) {
            resolve('success:', time)
        } else {
            reject('fail:, time)
        }
    }, 1000)
})
pm.then(
    res= > {
        console.log('success - res:, res)
    },
    rej= > {
        console.log('fail - rej:', rej)
    })
Copy the code
Promise,

Promise constructor: Promise(excutor)

  • Resolve, reject => {// async code}
  • Resolve function: Resolve (…) when the internal definition succeeds.
  • Reject: Reject (…) when an internal definition fails.

Note: Excutor immediately synchronously callbacks within the Promise, and asynchronous operations are performed in the executor

If (onResolved, onRejected) => {… }

  • Res => {}
  • Rej => {} rej => {}

Note: Specify a success callback for getting a successful RES and a failure callback for getting a failed rej, returning a new Promise object (the premise of chained calls)

Promise.prototype.catch :(onRejected) => {}

  • Rej => {} rej => {}

Then (undefined,onRejected); then(undefined,onRejected)

Promise.prototype.then determines the result of the new Promise object returned
  • Simple: is determined by the result of the callback function execution specified in then()
  • Detailed analysis:
    1. If an exception is thrown, the new Promise object returns with rejected, and the rej receives the returned exception
    2. If the returned Promise object is any value that is not a Promise object, the returned Promise object is in the Resolved state and the RES receives the returned data
    3. If another new Promise object is returned, this Promise object replaces the original Promise object returned by default
Promises concatenate multiple action tasks
cosnt pm = new Promise((resolve, reject) = > {
    setTimeout(() = > {
        const time = Date().now()
        if (time % 2= = =0) {
            resolve('success:', time)
        } else {
            reject('fail:, time)
        }
    })
})
pm.then(res= > {
        console.log('success - res1:', res)
        return 1
    }
).then(res= > {
    console.log('success - res2:', res)
    return new Promise((resolve, reject) = > {
            resolve('new success')
    })
}).then(res= > {
    console.log('success - res2:', res)
    return new Promise((resolve, reject) = > {
            reject('new fail')
    })
}).catch(rej= > {
    console.log('fail - rej:', rej)
})
Copy the code

Class

Basic use:

  • constructor
  • Static method
  • Getter/setter properties
class MathHandle {
    constructor (x, y) {
        this.x = x
        this.y = y
    }
    // Object methods
    add () {
        return this.x + this.y
    }
    // Static methods
    static say () {
        console.log('MathHandle')}// Properties: getter/setter get /set
    get longName () {
        return 'class' + this.x
    }
    set longName (val) {
        this.x = val
    }
}
const mObj = new MathHandle(1.2)
console.log(mObj.longName) // class-1
mObj.longName = 'hello'
console.log(m.longName) // class-hello
console.log(mObj.add()) // hello2
MathHandle.say() // 'MathHandle'

// Similar to the constructor
typeof MathHandle // 'function'
MathHandle === MathHandle.prototype.constructor // true
// the formal imitation of Java C# has lost its nature and individuality
m.__proto__ === MathHandle.prototype // The implicit stereotype of the instance === the display stereotype of the constructor
Copy the code

Inheritance:

  • Extends: inheritance
  • super(…) : passes arguments to the parent class, usually on the first line, and must precede this
class Animal {
    constructor (name='animal') {
        this.name = name
    }
    eat () {
        console.log(`The ${this.name} eat`)}}Extends is similar to dog.prototype = new Animal()
class Dog extends Animal {
    constructor (name='dog', age) {
        // Pass the parameter by super, which is usually the first line, and must precede this
        super(name)
        this.age = age
    }
    say () {
        console.log(`The ${this.name} ` + ` The ${this.age} ` + 'say')}}const dog = new Dog('Husky'.2)
dog.say()
dog.eat()
Copy the code

closure

Concept:

  • A closure is a function that has access to variables in the scope of another function
  • Is a function (for example, an internal function returns from a parent function)
  • Can access variables in the scope of the parent function (even if the parent function context has been destroyed)

Closure has three features:

  • Closures can access variables other than the current function
    function getFn () {
        let data = '315'
        function getData (str='getData') {
            console.log(str + data)
        }
        return getData('Current is:')
        // 'current is: 315'
    }
    getFn()
    Copy the code
  • The closure can access the variables defined by the outer function even if the outer function has returned
    function getFn () {
        let data = '315'
        function getData (str) {
            console.log(str + data)
        }
        return getData;
    }
    let conFn = getFn();
    conFn('Current is:') // 'current is: 315'
    Copy the code
  • Closures can update the value of an external variable
    function getFn () {
        let data = 0
        function getData (val) {
            count = val
            console.log(count)
        }
        return getData
    }
    let setCount = getFn()
    setCount(818) / / 818
    setCount(819) / / 819
    Copy the code

Deep copy

A deep copy copies all properties and the dynamically allocated memory to which the properties point

Parse (json.stringify (obj))

const obj = {
    name: 'lv'.age: 18.career: {
        companyName: 'every day'.years: 3}}const obj1 = JSON.parse(JSON.stringify(obj))
// Changes in obj1 do not affect obj at all
Copy the code

Note the following issues when using this method:

  • – undefined and symbol are ignored
  • Cannot serialize function
  • Cannot handle new Date() correctly, the solution is to convert it to a string or timestamp, as follows:
    // The solution is converted to a string or timestamp
    let date = (new Date()).valueOf()
    JSON.stringify(date) / / "1545620673267"
    JSON.parse(JSON.stringify(date)) / / 1545620658688
    Copy the code
  • Can’t handle regular

Method two: handwritten deep copy

  • Testing data types: Object. The prototype. ToString (target) : the type of the target string [Object typeName]
// Check type
const checkType = target= > {
  return Object.prototype.toString.call(target).slice(8, -1)}/ / copy
const deepClone = (target) = > {
  let result, targetType = checkType(target)
  if(targetType === 'Object') {
    result = {}
  }else if(targetType === 'Array') {
    result = []
  }else {
    return target
  }
  // Iterate over the target array
  for(let i in target) {
    if(target.hasOwnProperty(i)) {
      let value = target[i]
      if(checkType(value) === 'Object' || checkType(value) === 'Array') {
        result[i] = deepClone(value)
      }else {
        result[i] = value
      }
    }
  }
  // Return the final value
  return result
}
Copy the code

Object. The prototype. The toString () call () can determine the cause of the type

Object. The prototype. The toString () will return an Object of type string, output “[Object objType]” the objType is the constructor of the incoming parameters. Use call to specify arbitrary values and toString to return the constructor type to determine the type. Use apply/bind to determine the type

// call()
Object.prototype.toString.call('str') // "[object String]"
Object.prototype.toString.call(123) // "[object Number]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"

// apply()
Object.prototype.toString.apply({}) // "[object Object]"
Object.prototype.toString.apply([]) // "[object Array]"

// bind()
const f1 = Object.prototype.toString.bind({})
f1() // "[object Object]"
const f2 = Object.prototype.toString.bind([]) // "[object Array]"
Copy the code

Call, apply, bind

call

  • Basic applications:
    let a = { value: 1 }
    function getValue(name, age) {
      console.log(name)
      console.log(age)
      console.log(this.value)
    }
    getValue.call(a, 'lala'.24)
    // lala 24 1
Copy the code
  • Simulation implementation:
    Function.prototype.myCall = function (e) {
      console.log(e) // {value: 1}
      let context = e || window
      // Add the caller of myCall to the context method
      context._fn = this
      // Get all parameters except the first parameter
      let args = [...arguments].slice(1)
      console.log(args) // (2) ["lal", 28]
      // Call the method
      letresult = context._fn(... args)delete context._fn
    }
    getValue.myCall(a, 'lal'.28)
Copy the code

apply

  • Basic applications:
    let a = { value: 1 }
    function getValue(name, age) {
      console.log(name)
      console.log(age)
      console.log(this.value)
    }
    getValue.apply(a, ['yls'.26])
Copy the code
  • Simulation implementation:
    Function.prototype.myApply = function (e) {
      let context = e || window
      context._fn = this
      console.log(context)
      let args = arguments[1]
      console.log(args) // (2) ["yyy", 36]
      // This is an implicit bindingcontext._fn(... args)delete context._fn
      // 1. Store the first argument in.call/apply()
      // 2. Set this, the caller of.call/apply(), as the first parameter
      // 3. Store the remaining arguments of call/bind() except the first argument
      // 4. Call the stored this method with the first argument, passing the argument
      // 5. Delete the additional method added in the first argument
    }
    getValue.myApply(a, ['yyy'.36])
Copy the code

Call, apply simulation idea:

  1. Store the first argument in.call/apply()
  2. Method that sets this, the caller of.call/apply(), as the first parameter
  3. Store the remaining arguments of.call/bind() except the first argument
  4. Call the stored this method with the first argument, passing the argument
  5. Remove the additional method added in the first argument

bind

  • Simulation implementation:
    Function.prototype.myBind = function (thisArg) {
      if(typeof this! = ='function') {
        throw new TypeError(this + 'must be a function')}// Store the function itself
      var self = this
      // Handle the parameters of the first call to bind by removing thisArg's other arguments and turning them into an array
      var args = [].slice.call(arguments.1)
      // var args1 = [...arguments].slice(1)
      console.log(arguments, args, args1)
      var bound = function() {
        // Bind returns an array of arguments
        var boundArgs = [].slice.call(arguments)
        // select * from 'self' where 'this' =' self ';
        // And execute the self function to return the result
        return self.apply(thisArg, args.concat(boundArgs))
      }
      return bound
      // 1. Determine whether this is a function
      // 1.1 Store this
      // 2. Store all arguments except the first in.bind()
      // 3. Declare a function and return it
      // 3.1 Store the parameters in the declared function
      // 3.2 Call the apply method and pass the parameters
    }
    
    var obj = {name: 'if wear'}
    function original(a, b) {
      console.log(this.name)
      console.log([a, b])
    }
    var bound = original.myBind(obj, 1)
    bound(2) // If you wear [1, 2]
Copy the code

If the throttle

Throttling:

  • Core concept: If the alarm is triggered again within a specified interval, the alarm is ignored. The next interval is activated only after the specified interval is exceeded
// Method 1: use setTimeout
function throttle (fn, interval=500) {
    let flag = false
    return function (. args) {
        const _this = this
        if (flag) return
        flag = true
        setTimeout(() = > {
            fn.apply(_this, args)
            flag = false
        }, interval)
    }
}

// Plan 2:
function throttle (fn, interval=500) {
    let last = 0
    return function (. args) {
        const now = +new Date(a)if (now - last < interval) return
        last = now
        fn.apply(this, args)
    }
}
Copy the code

Stabilization:

  • Core concept: Each time an event is triggered, the original timer is deleted and the timer is restarted
function debounce (fn, delay=500) {
    let timeId = null
    return function (. args) {
        const _this = this
        if (timeId) clearTimeout(timeId)
        timeId = setTimeout(() = > {
            fn.apply(_this, args)
        }, delay)
    }
}
Copy the code

Shake + throttling: enhanced version

  • In case the event is triggered so frequently that there is no response, a response must be given to the user within a fixed period of time
function debounceStrong (fn, delay=500) {
    let timeId = null, last = 0
    return function (. args) {
        const _this = this
        const now = +new Date(a)if (now - last < delay) {
            clearTimeout(timeId)
            timeId = setTimeout(() = > {
                last = now
                fn.apply(_this, args)
            }, delay)
        } else {
            clearTimeout(timeId)
            last = now
            fn.apply(_this, args)
        }
    }
}
Copy the code

Example:

mounted () {
    window.addEventListener('scroll', throttle(this.handleShow), true)}methods: {
    handleShow () {
        // ...
        console.log('scroll')
    }
}
beforeDestroy () {
    window.removeEventListener('scroll', throttle(this.handleShow), true)}Copy the code