Js part

Quickly extract numbers from a string

Const STR = "12.6 px"; const numInt = parseInt(str); // numInt: 12 const numFloat = parseFloat(str); / / numInt: 12.6Copy the code

When the existence of an item in an array/object is determined by a condition

object

Assertion + object expansion operator

let isSleep = true; const obj = { name: "logan", ... isSleep && { age: 230 }, }; Obj = {name: "Logan ", age: 230}Copy the code

An array of

Ternary + array expansion operator (predicate expression will have a undefined, arrays will not be filtered by default)

    const hasSecond = true
    const arr = [
        {
            num: 1
        },
        ...hasSecond ?  [{
            num: 2
        }] : []
    ]
Copy the code

Delete the array with the length attribute

const arr = [0, 1, 2, 3, 4, 5]; arr.length = 0; // arr changes to []Copy the code

Fortunately, in VUe3, the VUE team solved this problem by replacing Object.defineProperty with a Proxy and waiting for the official release of VUe3.

Comma operator

The comma operator evaluates each of its operands (left to right) and returns the value of the last operand.

const history = []; Const push = val => (history.push(memory(val)), val);Copy the code

Deconstruct where expressions are commonly used

For of expression line destruct

    const cacheList = [
        {
            id: 1,
            date: "2020-05-18",
            timeout: 2569
        },
        {
            id: 3,
            date: "2020-04-16",
            timeout: 7863
        },
        {
            id: 2,
            date: "2020-03-21",
            timeout: 6387
        }
    ]
    
    for(let {id, date, timeout} of cacheList) {
        console.log(id);
        console.log(date);
        console.log(timeout);
    }
Copy the code

Retrieve the remaining attributes of the object

The vue component passes down the props syntax with $attrs and $listener, but react does not provide this scheme, so when the props need to be passed across several layers, we can use the deconstruction method to avoid making our component a props mover.

The following code

Function Parent() {const [list, setList] = useState([]); function Parent() {const [list, setList] = useState([]); const produce = [ { id: 0, name: "x23" } ]; Return (<child list={list} produce={produce} change={setList}/>)}/ / Pass function child (props) {const {list, ... rest} = props; return ( <Grandson {... Function GrandSon(props) {return (<> <ul> {produce. Map (({id, name}) => <Cell key={id} title={name}>)} </ul> <button onClick={change}></button> </> ) }Copy the code

Similarly, this approach can be used in vUE, for example, if you write a table component and want to add custom fields in multiple locations, you can use V-bind to do this.

(The inspiration here comes from the table source section of Layui)

<th v-for="({title, ... rest}) in col" :key="title" v-bind="rest" > {{title}} </th>Copy the code

Parameters are destructed directly, reducing unnecessary temporary variable declarations

    window.addEventListener("wheel", function({clientX, clientY}) {
        console.log({clientX, clientY});
    });
Copy the code

Dynamic property name and property name expression

const type = "email"; const params = { username: "James Rhodes", password: "war machine Rox with an X", [type]: "[email protected]", } const key = "password"; console.log(params[key]); // War machine Rox with an XCopy the code

For example, if you want to dynamically value values in vUE (vue(2.6.0+) dynamic attribute)

<component :[key]="value"></component>
Copy the code

The default value is used

||

    function Jarvis(options) {
        this.name = options.sir || "Tony Stark";
    }
Copy the code

Destruct expression

function Jarvis(options) { const {sir = "Tony Stark"} = options; this.name = sir; // const {Sir :name} = options; // this.name = name; }Copy the code

(negligible) ES11 provides?? operation

    function Jarvis(options) {
        this.name = options.sir ?? "Tony Stark";
    }
Copy the code

Alternative cssText dom. Style. XXX

const dom = document.querySelector(".wrapper"); dom.style.cssText = "width:20px; height:20px; border:solid 1px gray;" ;Copy the code

Use Array’s factory function to create an Array of a specific length

Array.from(arrayLike[, mapFn[, thisArg]])

  • ArrayLike A pseudo-array object or iterable that you want to convert to an array.
  • MapFn Optional If this parameter is specified, each element in the new array executes the callback function.
  • ThisArg Optional This object is optional when the callback function mapFn is executed.
Array.from({ length: 10 }, (v, i) => i + 1); // Output [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]Copy the code

I now use this feature to mock data

    app.get('/getProduces', function (req, res) {
        res.send({
            code: 200,
            data: Array.from({length: 6}, (v, i) => ({
                name: `produce - ${i}`,
                url: `/view/produce/${i}.html`,
                type: Math.round(Math.random())
                    ? "new"
                    : "default",
                num: Math.round(Math.random() * 10000),
            }))
        });
    });
Copy the code

Adds data to the array header

Sometimes you might make a stack structure out of arrays

const arr = ["Ferrie", "Natasha"]; arr.unshift("Tony"); // Arr becomes ["Tony", "Ferrie", "Natasha"]Copy the code

Reduce scope lookups

For example, the following code runs in global scope:

<script> var header = document.querySelector("#header"); header.style.cssText = `position: sticky; top: ${offsetTop}px; `; </script>Copy the code

In a script tag, the context of the code is in the global scope, and the compiler is slow to process the global scope because of its complexity. Just like the header variable above, the second line needs to look up the variable in the global scope when it is used. Assuming the header is used in a loop, that might be efficient. So avoid global scopes and choose local scopes instead:

For example 🌰, closure scope

<script> ! function(){ var header = document.querySelector("#header"); header.style.cssText = `position: sticky; top: ${offsetTop}px; `; }() </script>Copy the code

Avoid overusing closures

Even if closures are useful, don’t abuse them; variables in closures are scoped independently. The compiler looks for variables from the current scope to the parent scope. So the depth of closure nesting affects variable lookup time.

For example, 🌰, we have a flow function that defines an animate function. After animate, there is a constant location. Target and rate are in the parent scope of animate. The lookup takes longer than the location,

Function flow(target, rate = 0) {rate += 0.1; Function animate() {const location = getLocation(target.location, 0.5); return Tween.get(target).to({rate}); } return animate(); }Copy the code

You can pass target and rate to animate as parameters. In this way, their scope becomes the same, and the read time is just a matter of how the compiler handles the difference between constants and variables.

Function flow(target, rate = 0) {rate += 0.1; function animate(target, rate) { return Tween.get(target).to({rate}); } return animate(target, rate); }Copy the code

If a global variable needs to be used frequently, you can cache it with a local variable (🌰: I got it myself).

function call() { if(window.location.origin ! == "xxxxxx") return; const hash = getHash(window.location.href); const url = `/api/radio/${window.location.search}/${hash}`; }Copy the code

Using window.location multiple times, we can cache it in the function scope,

function call() { const {location} = window; if(location.origin ! == "xxxxxx") return; const hash = getHash(location.origin, location.hash); const url = `/api/radio/${location.search}/${hash}`; }Copy the code

Alternative = = = = =

Two reasons

  • 1. Js is a weakly typed language.= =Data types are ignored in favor of more precise ones for better readability= = =operation
  • 2. Better compilation speed at compiler processing= =Will first convert the two variables to the same type, and then compare whether the values are equal; And processing= = =Determines whether the types are the same, and then decides whether to compare values for equality.

String template

Discard string concatenation or arrays for better readability. Join (“”), select string template

Const STR = ` original price: ${price}, discount: ${discount}, the final price: ${(price discount). ToFixed (2)} `;Copy the code

The priority of variable modifiers: const > let > var

According to?

var

  1. You can redeclare it
  var starLord = "fool";
  starLord = "very fool";
  var starLord = "foolish";
Copy the code
  1. Can be variable promoted
function () { console.log(name); Var name = "Tony"}Copy the code
  1. Span block scope
  • Block scope: {}, conditions, {} of loop statements
{ var Tony = "Iron Man"; } console.log(Tony); If (true) {var Steve = "caption"; } console.log(Steve ); // caption let i = 0; while(i++ < 2) { if(i === 1) { var thor = "Fatty"; } } console.log(thor); // FattyCopy the code

let

Can only be used in the current block-level scope

const

  1. Const is more semantic, reminding developers that the variable should not be changed;
  2. The compiler optimizes const to read constants faster than variables. The essential difference is how the compiler handles it internally.

Use promise.all for correct posture

Before ES11 promise. allSettled appeared, promise. all collected promises. When any one of them was wrong, no result could be obtained. In this case, you could perform a catch operation on the Promise objects collected by ALL to manually process err

const p1 = new Promise(...) const p2 = new Promise(...) const p3 = new Promise(...) Promise.all([p1,p2,p3]).then(...) .catch(err => err)Copy the code

Multiple loading conflicts

Introduce a variable loadingCount for counting,

When loading, check whether the quantity is 0. If the condition is met, +1 is used.

If the value is close, -1 is used first. If the value is 0, the command is executed

let loadingCount = 0
function open() {
    if(loadingCount > 0) return

    loadingCount++;
    loading.open();
}
function close() {
    loadingCount--
    if(loadingCount === 0) {
        loading.close()
    }
}
Copy the code

After triggering the parent component event in vUE, retrieve the props

    props: {
        msgList: ...
    }
Copy the code
this.$emit("sendMsg", id); $nextTick(() => {this.showdetail = this.msglist && this.msglist. Length > 0; });Copy the code

Conflicts between canvas drawing and clearing functions

Remember to call Context.beginPath () to clear, otherwise the previous line still exists

The CSS part

Debug UI tips

Try adding this style to the debug area (#app)

    #app {
        outline: 1px #000 solid;
    }
Copy the code

Can automatically adapt to the wide/high background image Mosaic scheme

whendomIn the background is a picture whose width and height are determined by the content,

How to achieve the image adaptive height at this time?

(Flicker because we changed the width and height causing the browser to redraw and rearrange)

<style> .box { width: 100px; height: auto; // Change background height arbitrarily: url(/static/img/box-bg-top.png) top no-repeat, url(/static/img/box-bg-bottom.png) bottom no-repeat; } .box:before { content: ''; position: absolute; z-index: -1; top: 80px; right: 0; bottom: 80px; left: 0; background: url(/static/img/box-bg-center.png) repeat; } </style> <body> <div class="box"> </div> </body>Copy the code

Dom itself implements the header and tail of the image through background-position and background-repeat, and then implements the adaptive part in the middle with pseudo-elements

Use pointer-Events properly

In a super-large DOM, with only one small child DOM requiring mouse events, we can do this

    .parent {
        width: 600px;
        height: 500px;
        pointer-events: none;
    }
    .close {
        float: right;
        width: 10px;
        height: 10px;
        pointer-events: visible;
    }
Copy the code

CSS selectors

After the x th (excluding the x th)

    li:nth-of-type(n+x) {
        ...
    }
Copy the code

X th and before (inclusive of x th)

    li:nth-of-type(-n+x) {
        ...
    }
Copy the code

Not selector (exclude one)

    li:not(:last-child) {
        background: #08627f;
    }
Copy the code

Font spacing and center

Most people just set spacing to spacing. This causes text to get too big and out of center, so you need the same text-indent value for the first line to be centered

 .text {
    letter-spacing: 12px;
    text-indent: 12px;
 }
Copy the code

transform

Instead of left/top, can effectively avoid redrawing

Redrawing and rearranging will cause a splash screen, as you can see in the example above

    .dot {
        transform: translate3d(10px, 16px, 0);
    }
Copy the code

Force GPU rendering on using translateZ

    .dot {
        transform: translateZ(0);
    }
Copy the code

However, if GPU acceleration is enabled, frequent flickering or jitter may occur in the browser. This can be solved as follows:

    .dot {
        -webkit-backface-visibility:hidden;
        -webkit-perspective:1000;
    }
Copy the code

Absolute positioning, centering problem with uncertain width and height

    .box {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
    }
Copy the code

Give thead border

    table {
        border-collapse:collapse;
    }
    thead {
        border: 1px #0af solid;
    }
Copy the code

Image distortion free

    img {
        object-fit: cover;
    }
Copy the code

Sprites fit the screen

@screen_width: 1920; img { background-image: url("..." ); background-position: 15px 30px; background-size: calc(100vw / @screen_width * 160); }Copy the code

Input to the border

    border: none;
    outline: none;
Copy the code

The user resizes the DOM

Slightly less compatible

    .resize {
        resize:both;
    }
Copy the code

CSS Smooth scrolling

    scroll-container {
        scroll-behavior: smooth;
    }
Copy the code
    <nav>
        <a href="#page-1">1</a>
        <a href="#page-2">2</a>
        <a href="#page-3">3</a>
    </nav>
    <scroll-container>
        <scroll-page id="page-1">1</scroll-page>
        <scroll-page id="page-2">2</scroll-page>
        <scroll-page id="page-3">3</scroll-page>
    </scroll-container>
Copy the code

Height is a percentage when the text is vertically centered

Use table-cell and vertical-align

    <style>
        .parent {
            display: table;
            width: 600px;
            height: 50%
        }
        .parent a {
            display: table-cell;
            vertical-align: middle;
        }
    </style>
    <div class="parent">
        <a href="#page-1">1</a>
        <a href="#page-2">2</a>
        <a href="#page-3">3</a>
    </nav>
Copy the code

Var takes the element attribute value

Class, ID, and Keyframes can all be used to directly retrieve attributes on an element

    <template>
        <div v-for="(item, index) in list"
             :style="{'--y': `${index*60}deg`}"
             class="around-item u_3d">
            <div class="content">{{item}}</div>
        </div>
    </template>
    <style>
        @keyframes around-self {
            0% {
                transform: rotateY(calc(var(--y) * -1));
            }
            100% {
                transform: rotateY(calc(var(--y) * -1 - 360deg));
            }
        }
        .content {
            animation: around-self 10s linear 0s infinite;
        }
    </style>
Copy the code

other

When webpack configures the Loader, narrow the search scope by using test, exclude, and include

    module: {
        rules: [
          {
            test: /\.vue$/,
            loader: 'vue-loader',
            include: [resolve('src/components'), resolve('src/modules')],
            options: vueLoaderConfig
          },
          {
            test: /\.js$/,
            loader: 'babel-loader',
            include: [resolve('src'), resolve('node_modules/webpack-dev-server/client')],
            exclude: /node_modules/
          },
        ]
    }
Copy the code

Modifiers for script and style tags

preload

Resources are loaded before DOM rendering, usually some of the logic responsible for the first screen rendering

    <link rel="preload" href="index.css">
Copy the code

Prefetch, DNS – prefetch

When the page is loaded and there is no work to do, loading is usually some script related to user interaction, such as a third-party pop-up layer

    <link rel="prefetch" href="next.css">
    <link rel="dns-prefetch" href="//example.com">
Copy the code

No modifiers (asynchronous, no blocking)

Pause parsing document. Request script to execute script to continue parsing document

<script src="index.js" ></script>
Copy the code

defer

Js and user.js are downloaded in parallel, in order of the page, after the execution of other synchronization scripts, and before the execution of DOMContentLoaded events, home.js and user.js are executed successively.

<script src="home.js" defer></script>
<script src="user.js" defer></script>
Copy the code

async

When the script is downloaded, it is immediately executed. The execution sequence of the script is uncertain, and the execution stage is uncertain. It may be executed before or after DOMContentLoaded

<script src="home.js" async></script>
<script src="user.js" async></script>
Copy the code

The image format is webP

Small size, fast request speed, but there are compatibility problems, need to be handled manually