Specification purposes

In order to improve the efficiency of team collaboration, facilitate the optimization and maintenance of the front-end, output high-quality documents.

The basic principle of

Separation of structure, style and behavior

Try to make sure that documents and templates contain only HTML structure, that styles are in style sheets, and that behavior is in scripts.

The indentation

Do not use Tab or a combination of Tab and space.

File encoding (generally generated automatically by the compiler)

Use UTF-8 encoding without BOM.

Specify encoding in HTML
;

You don’t need to use @charset to specify the encoding of the stylesheet, which defaults to UTF-8 (see @charset);

Always use lowercase letters

<! <img SRC = "<img SRC ="google.png" alt="Google"> <! --> <A HREF="/">Home</A>
Copy the code
/* recommend */ color:#e5e5e5;/* not recommended */ color:#E5E5E5;
Copy the code

Omit the URL protocol part of the external link resource

Omit HTTP/HTTPS protocol in URL of external link resources (pictures and other media resources), make URL become relative address, avoid Mixed Content problem and reduce file bytes.

The URL of other protocols (FTP, etc.) is not omitted.

<! -- recommended --> <script SRC ="//www.xxx.cn/statics/js/autotrack.js"></script> <! --> <script SRC ="http://www.xxx.cn/statics/js/autotrack.js"></script>
Copy the code
Recommend / * * /. Example {background: url (/ / www.google.com/images/example); } / * * / is not recommended. Example {background: url (http://www.google.com/images/example); }Copy the code

Unified annotation

The configuration editor provides shortcuts to output agreed comment patterns (as described in the ESlint specification).

HTML comments

  • Module annotation
<! <div class="article-list">... </div>Copy the code
  • Block comments
<! -- @name: Drop Down Menu @description: Style of top bar drop down menu. @author: Ashu([email protected]) -->Copy the code

CSS comment

Component blocks and sub-component blocks and declaration blocks are separated by an empty line, and sub-component blocks are separated by three empty lines.

/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = component pieces = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * / / * subcomponent ============================================================================ */ .selector { padding: 15px; margin-bottom: 15px; } / * subcomponent block = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * /. The selector - secondary {display:  block; }. Selector -three {display: span; }Copy the code

JavaScript comments

  • Single-line comments

    A row must be exclusive. // Followed by a space, indented to match the next line of commented code.

  • Multiline comment

    Avoid using /… / Multiline comments like this. Use multiple single-line comments when you have multi-line comment content.

  • Function/method comments

    Function/method comments must contain the description of the function and must be identified with comments if there are arguments and return values;

    Parameter and return value annotations must contain type information and description;

    You can use the @inner identifier when the function is internal and not externally accessible.

@param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=returnObject} Return value Description */function foo(p1, p2, p3) {
    var p3 = p3 || 10;
    return {
        p1: p1,
        p2: p2,
        p3: p3
    };
}
Copy the code

File comment

File comments are used to tell readers unfamiliar with the code what is contained in the file. You should provide the general content of the file, its author, dependencies, and compatibility information. As follows:

/**
 * @fileoverview Description of file, its uses and information
 * about its dependencies.
 * @author [email protected] (Firstname Lastname)
 * Copyright 2015 Meizu Inc. All Rights Reserved.
 */
Copy the code

Code validation (rarely needed)

  • Use the W3C HTML Validator to validate your HTML code.
  • Use the W3C CSS Validator to validate your CSS code.

Code validation is not the end in itself. The real goal is to give developers, after going through this process many times, a good understanding of what syntax or writing is not standard or recommended, even if they are forced to use non-standard writing in certain situations.

HTML

Try to follow HTML standards and semantics, but not at the expense of usability. Use as few tags as possible and keep complexity to a minimum at all times.

General agreement

The label

  • Self-closing labels do not need to be closed (for example, IMG Input BR HR).
  • Optional closing tag, which must be closed (for example:
  • Or a);

  • Minimize the number of labels.
<img src="https://atts.w3cschool.cn/attachments/image/cimg/google.png" alt="Google">
<input type="text" name="title"> <ul> <li>Style</li> <li>Guide</li> </ul> <! --> <span class="avatar">
  <img src="..."> </span> <! --> <img class="avatar" src="...">
Copy the code

The Class and ID

  • Classes should be named after functionality or content, not presentation;
  • The class and ID words are lowercase letters. If there are multiple words, separate them by hyphens (-).
  • Use unique ids as Javascript hooks while avoiding creating classes with no style information;
<! --> <div class="j-hook left contentWrapper"></div> <! <div id="j-hook" class="sidebar content-wrapper"></div>
Copy the code

Attribute order

HTML attributes should appear in a specific order to ensure readability.

  • id
  • class
  • name
  • data-xxx
  • src, for, type, href
  • title, alt
  • aria-xxx, role
<a id="..." class="..." data-modal="toggle" href="# # #"></a>

<input class="form-control" type="text">

<img src="..." alt="...">
Copy the code

quotes

Attribute is defined using double quotation marks.

<! --> <span id='j-hook'class=text>Google</span> <! --> <span id="j-hook" class="text">Google</span>
Copy the code

nested

A does not allow div to be nested, which is a semantic nesting constraint, as opposed to a strict nesting constraint, such as a does not allow a to be nested.

Strict nesting constraints are not allowed in all browsers; With semantic nesting constraints, browsers are mostly fault-tolerant, and the resulting document tree may differ from one another.

Semantic nesting constraints

  • <li>Used for<ul><ol>Under;
  • <dd>.<dt>Used for<dl>Under;
  • <thead>.<tbody>.<tfoot>.<tr>.<td>Used for<table>Under.

Strict nesting constraints

  • An inline-level element, which can only contain text or other inline-level elements;
  • <a>Interactive elements cannot be nested in<a>,<button>,<select>And so on;
  • <p>Block level elements cannot be nested in<div>,<h1>~<h6>,<p>,<ul>/<ol>/<li>,<dl>/<dt>/<dd>,<form>And so on.

Boolean properties

In HTML5 specification, disabled, checked, selected and other attributes do not need to set values.

<input type="text" disabled>

<input type="checkbox" value="1" checked>

<select>
  <option value="1" selected>1</option>
</select>

Copy the code

semantic

HTML without CSS is a semantic system, not a UI system.

In addition, the semantic HTML structure helps the machine (search engine) to understand, on the other hand, when multiple people collaborate, can quickly understand the developer’s intention.

Common tag semantics (not listed in H5)

The label The semantic
<p> The paragraph
<h1> <h2> <h3> ... The title
<ul> No sequence
<ol> An ordered list
<blockquote> Large section of the reference
<cite> General reference
<b> Bold for style
<strong> Bold for emphasis
<i> Lean for style’s sake
<em> Slant for emphasis
code Code identification
abbr abbreviations
. .

The sample

Treat the page you build as a book, matching the semantics of the tag to its function and meaning;

  • Book Title:<h1>
  • The title of each chapter of the book:<h2>
  • Article titles in chapters:<h3>
  • Subheadings/subheadings:<h4> <h5> <h6>
  • A paragraph of a chapter:<p>

HEAD

The document type

Adding a standard Mode declaration for the first line of each HTML page ensures consistent performance across browsers.

<! DOCTYPE html>Copy the code

Language attributes

Why use lang=” zh-cmn-hans “instead of lang=” zh-cn” as we usually write? Please refer to the discussion on Zhihu: should the declaration in the header of the web page be lang=”zh” or lang=”zh-cn”?

<! -- Chinese --> < HTML lang="zh-Hans"> <! -- Simplified Chinese --> < HTML lang="zh-cmn-Hans"> <! -- Traditional Chinese --> < HTML lang="zh-cmn-Hant"> <! -- English --> <html lang="en">
Copy the code

A character encoding

  • Use UTF-8 code without BOM as file format;
  • The character encoding meta must be the first direct child of the head;
<html>
  <head>
    <meta charset="utf-8">... </head> <body> ...... </body> </html>Copy the code

IE Compatible Mode

The latest version of Internet Explorer and Chrome kernel are preferred

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
Copy the code

SEO optimization

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <! -- SEO --> <title>Style Guide</title> <meta name="keywords" content="your keywords">
    <meta name="description" content="your description">
    <meta name="author" content="author,email address">
</head>
Copy the code

viewport

  • Viewport: generally refers to the size of the browser window content area, excluding toolbar, TAB, etc.
  • Width: browser width, output device page visible area width;
  • Device-width: device resolution width, output device screen visible width;
  • Initial-scale: indicates the initial scaling scale.
  • Maximum-scale: the maximum scale;

Optimized for mobile devices, set the width and initial scaling of the visible area.

<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
Copy the code

IOS icon

  • Apple-touch-icon images are automatically processed into rounded corners and highlights.
  • Apple-touch-icon-precomposed forbade the system to automatically add effects and directly display the original design picture;
<! -- iPhone and iTouch, default 57x57 pixels, must have --> <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png"> <! <link rel= --> <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-72x72-precomposed.png" sizes="72x72"> <! -- Retina iPhone and Retina iTouch, 114x114 pixels, available, but recommended --> <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-114x114-precomposed.png" sizes="114x114"> <! <link rel= <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-144x144-precomposed.png" sizes="144x144">
Copy the code

favicon

When favicon is not specified, most browsers request favicon.ico in the Web Server root. To keep favicon accessible and avoid 404, you must follow one of two methods:

Place the favicon.ico file in the Web Server root directory; Specify favicon using link;

<link rel="shortcut icon" href="path/to/favicon.ico">
Copy the code

The HEAD template

<! DOCTYPE html> <html lang="zh-cmn-Hans">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Style Guide</title>
    <meta name="description" content="No more than 150 characters">
    <meta name="keywords" content="">
    <meta name="author" content="name, [email protected]"> <! -- Add viewPort for mobile devices --> <meta name="viewport" content="Width = device - width, initial - scale = 1.0"> <! -- iOS icon --> <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png">

    <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
    <link rel="shortcut icon" href="path/to/favicon.ico">
</head>
Copy the code

CSS

General agreement

Code organization

  • Organize code snippets by component;
  • Develop consistent annotation specifications;
  • Component blocks and sub-component blocks and declaration blocks are separated by an empty line, and sub-component blocks are separated by three empty lines.
  • If you use multiple CSS files, split them as components rather than pages, because pages are reorganized and components are moved.

Good annotation is very important. Set aside time to describe how components work, their limitations, and how they are built. Don’t let other members of your team guess at the purpose of a piece of code that isn’t generic or obvious.

Tip: By configuring the editor, you can provide shortcuts to output agreed-upon comment patterns.

/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = component pieces = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * / / * subcomponent ============================================================================ */ .selector { padding: 15px; margin-bottom: 15px; } / * subcomponent block = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * /. The selector - secondary {display:  block; }. Selector -three {display: span; }Copy the code

The Class and ID

  • Use semantic and generic naming methods;
  • Use hyphens – as ID and Class name delimiters, not camel names and underscores;
  • Avoid too many selector nesting levels, as little as 3 levels;
  • Avoid using selectors in combination with Class and ID.

For performance reasons, avoid element selectors overlaid with Class and ID when not necessary.

Mixing element selectors with ID and Class also violates separation of concerns. If the HTML tag is modified, you have to modify the CSS code, which is not conducive to later maintenance.

/* Not recommended */.red {}.box_green {}.page.header.login#username input {}
ul#example {}Recommend * / / *#nav {}
.box-video {}
#username input {}
#example {}
Copy the code

Declarative block format

  • When grouping selectors, keep separate selectors in a row.
  • Add a space before the left parenthesis {of the declaration block;
  • The declaration block’s closing parenthesis} should be a separate line;
  • A space should be added after:;
  • Statements should be declared with semicolons; At the end.
  • Attribute values usually separated by commas should be followed by a space;
  • Values in parentheses RGB (), RGBA (), HSL (), HSLA (), or rect(), separated by commas, but without a space after commas;
  • For attribute values or color parameters, omit the 0 before the decimal less than 1 (for example,.5 instead of 0.5; -.5px instead of -0.5px);
  • Hex values should be all lowercase and as short as possible, for example, # FFF instead of # FFFFFF;
  • Avoid specifying units for 0 values, for example, margin: 0; Instead of margin: 0 px; .
/* not recommended */.selector,.selector-secondary,.selector[type=text] { padding:15px; margin:0px 0px 15px; Background - color: rgba (0, 0, 0, 0.5); box-shadow:0px 1px 2px#CCC,inset 0 1px 0 #FFFFFF} /* recommend */.selector,.selector-secondary,.selector[type="text"] { padding: 15px; margin-bottom: 15px; Background - color: rgba (0, 0, 5); box-shadow: 0 1px 2px#ccc, inset 0 1px 0 #fff;
}
Copy the code

The statement sequence

The related attributes should be written in a recommended style sequence

  1. Positioning
  2. Box model
  3. Typographic
  4. Visual

Positioning is at the top of the list because it removes elements from the normal document flow and also overwrites box Model-related styles. The box model determines the size and location of the components and therefore comes second.

The other attributes only affect the inside of the component or do not affect the first two sets of attributes, and therefore fall behind.

.declaration-order {
  /* Positioning */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;

  /* Box model */
  display: block;
  box-sizing: border-box;
  width: 100px;
  height: 100px;
  padding: 10px;
  border: 1px solid #e5e5e5;
  border-radius: 3px;
  margin: 10px;
  float: right;
  overflow: hidden;

  /* Typographic */
  font: normal 13px "Helvetica Neue", sans-serif; The line - height: 1.5; text-align: center; /* Visual */ background-color:#f5f5f5;
  color: #fff;
  opacity: .8;

  /* Other */
  cursor: pointer;
}
Copy the code

quoting

The URL (), property selector, and property value use double quotation marks. Is quoting the value of URL () really necessary?

/ * * / @ import is not recommended url (/ / www.google.com/css/maia.css); html { font-family:'open sans', arial, sans-serif; } /* recommend */ @import url("//www.google.com/css/maia.css");

html {
  font-family: "open sans", arial, sans-serif;
}

.selector[type="text"] {}Copy the code

Location of Media Query

Place media queries as close to relevant rules as possible. Don’t pack them in a single style file or put them at the bottom of the document. If you split them up, they’ll just be forgotten.

.element { ... }
.element-avatar { ... }
.element-selected { ... }

@media (max-width: 768px) {
  .element { ...}
  .element-avatar { ... }
  .element-selected { ... }
}
Copy the code

Do not use @import

Compared to , @import is much slower, not only adding extra requests, but also causing unexpected problems.

Alternatives:

  • Use multiple elements;
  • Compile multiple CSS files into a single file with a CSS preprocessor like Sass or Less;
  • Other CSS file merging tools;

See Don’t use @import;

Link style order:

A :link -> a:visited -> a:hover -> a:active (LoVeHAte)

You do not need to add the browser vendor prefix

Using Autoprefixer to automatically add the browser vendor prefix, you can write CSS using standard CSS without adding the browser prefix.

Autoprefixer uses Can I Use to add browser vendor prefixes to corresponding CSS codes according to compatibility requirements.

Module organization

Any CSS code over 1,000 lines, you’ve experienced something like this:

  1. What does this class actually mean?
  2. Where is this class used?
  3. If I create an XXoo class, will there be a conflict?

The Reasonable System for CSS Stylesheet Structure aims to solve these problems. It is not a framework, but a specification that allows you to build more robust and maintainable CSS code.

Components

Think from the perspective of Components and treat each module of your site as a separate component.

Naming Components

Components are named with at least two words, separated by -, for example:

  • (.like-button)
  • The search box (. Search – form)
  • Article card (.article card)

Elements

Elements are Elements in Components

Naming Elements

The class name of Elements should be as one-word as possible.

.search-form { > .field { /* ... */ } > .action { /* ... * /}}Copy the code

On multiple words

For Elements class names that require two or more words, do not use hyphens and underscores. Instead, connect them directly.

.profile-box { > .firstname { /* ... */ } > .lastname { /* ... */ } > .avatar { /* ... * /}}Copy the code

Avoid tag selectors

Use classnames whenever possible. The label selector works fine, but its performance is weak and its meaning is ambiguous.

. The article - card {> h3 {/ * ✗ get * /} >. The name {/ * ✓ better * /}}Copy the code

Variants

Components and Elements will probably own Variants.

Naming variants

Variants’ classname should be preceded by an underline –

.like-button { &.-wide { /* ... */ } &.-short { /* ... */ } &.-disabled { /* ... * /}}Copy the code

Element variants

.shopping-card { > .title { /* ... */ } > .title.-small { /* ... * /}}Copy the code

Dash Prefixes (underlined prefix)

Why use a hyphen as a prefix for variants?

  • It avoids ambiguity and Elements
  • CSS classes can only start with a word and an _ or –
  • A dash is easier to print than an underscore

Layout = Layout

Avoid positioning Properties

Components should be reusable in different contexts, so avoid setting the following properties:

  • Positioning (position, top, left, right, bottom)
  • Floats (float, clear)
  • Margins (margin)
  • Dimensions (width, height) *

Fixed dimensions

The avatar and logos elements should have a fixed size (width, height…) .

Define Positioning in parents

If you need to set a location for a component, it should be handled within the component’s parent element. For example, in the following example, widths and floats are applied to a list component(.article-list). Not component(.article-card) itself.

  .article-list {
    & {
      @include clearfix;
    }

    > .article-card {
      width: 33.3%;
      float: left; } } .article-card { & { /* ... */ } > .image { /* ... */ } > .title { /* ... */ } > .category { /* ... * /}}Copy the code

Nesting Avoid over-nesting

It is easy to get out of control when multiple nesting occurs. Keep no more than one nesting.

  /* ✗ Avoid: 3 levels of nesting */
  .image-frame {
    > .description {
      /* ... */

      > .icon {
        /* ... */
      }
    }
  }

  /* ✓ Better: 2 levels */
  .image-frame {
    > .description { /* ... */ }
    > .description > .icon { /* ... */ }
  }
Copy the code

Apprehensions

  • Underline – it’s a bad pile of stuff: you can always choose to use it, just keep Components, Elements in mind.
  • I sometimes can’t think of two words: some components do use one word for meaning, such as alert. But you can use suffixes to make it more conscious.

For example, block-level elements:

  • .alert-box
  • .alert-card
  • .alert-block

Or inline level elements

  • .link-button
  • .link-span

Summary

  • Think in terms of Components, name it with two words (.screenshot-image)
  • Elements in Components, named after a word (.blog-post.title)
  • Patterns will later be prefix with a dash (.shop-banner.-with-icon).
  • Components can be nested with each other
  • Remember, you can make things easier by inheritance

Less specification

Code organization

The code is organized in this order:

  1. @import
  2. Variable declarations
  3. Style statement
@import "mixins/size.less";

@default-text-color: # 333;

.page {
  width: 960px;
  margin: 0 auto;
}
Copy the code

@ import statements

The @import statement must enclose the text in a pair of quotation marks. The suffix.less must not be omitted. Use both ‘and’ quotation marks, but within the same project needs to be uniform.

/* not recommended */ @import"mixins/size";
@import 'mixins/grid.less'; /* Recommend */ @import"mixins/size.less";
@import "mixins/grid.less";
Copy the code

Mixin

  1. When defining a mixin, if the mixin name is not a className that needs to be used, parentheses must be used, otherwise it will be printed to CSS even if it is not called.

  2. If you are mixing a mixin that does not output itself, you need to add parentheses after the mixin (even if no arguments are passed) to distinguish whether it is a className.

/* not recommended */. Big-text {font-size: 2em; } h3 { .big-text; .clearfix; } /* recommend */.big-text() { font-size: 2em; } h3 { .big-text(); /* 1 */ .clearfix(); / * * / 2}Copy the code

Avoid excessive levels of nesting

  • Limit the nesting depth to 2 levels. For nesting beyond 3 levels, re-evaluation is given. This avoids overly verbose CSS selectors;
  • Avoid lots of nested rules. Interrupt when readability is affected. It is recommended to avoid nesting rules with more than 20 lines.

String interpolation

Variables can be embedded in strings in a similar way to Ruby and PHP, with structures like @{name} : @base-URL: “assets.fnord.com”; background-image: url(“@{base-url}/images/bg.png”);

Performance optimization

Choose high-consumption styles carefully

Do you really understand backflow and redraw?

High-consumption attributes require a lot of browser calculation before drawing:

  • box-shadows

  • border-radius

  • transparency

  • transforms

  • CSS Filters (Performance killer)

    [Note] : The problem with using filter is that it blocks rendering and freezes the browser when browsing to load images. It also increases memory consumption, and it works on an element rather than an image, so the problem is worse. The best solution is to avoid AlphaImageLoader altogether and use PNG8 instead.

Avoid excessive rearrangements

When a rearrangement occurs, the browser needs to recalculate the layout position and size.

Common rearrangement elements:

  • width
  • height
  • padding
  • margin
  • display
  • border-width
  • position
  • top
  • left
  • right
  • bottom
  • font-size
  • float
  • text-align
  • overflow-y
  • font-weight
  • overflow
  • font-family
  • line-height
  • vertical-align
  • clear
  • white-space
  • min-height

Use Display properties correctly

The Display attribute will affect the rendering of the page. Use it wisely.

  • Display: Inline should not be used after width, height, margin, padding, or float;
  • Display: Float should not be used after inline-block;
  • Display: vertical-align should not be used after block;
  • Display: table-* should not use margin or float;

Don’t abuse of Float

Float is very computationally intensive during rendering and should be used sparingly.

Animation performance optimization

The realization principle of animation is to use the phenomenon of “visual transient” of human eyes to continuously play several still pictures in a short period of time, so that the naked eye will misperceive the picture as “moving” due to the illusion of visual residual images.

Basic concepts of animation:

  • Frame: In the animation process, each still picture is a “frame”;
  • Frame rate: The number of still frames played per second (Frame per second).
  • Frame duration: the dwell time of each still image, usually in ms(ms);
  • Frame drop: In fixed frame rate animation, a frame that is longer than the average frame length, resulting in subsequent frames being squeezed and lost.

The average browser render refresh rate is 60 FPS, so animations at 50-60 FPS on a web page will be pretty smooth and comfortable.

  • If you are using javaScript based animation, try to use requestAnimationFrame. Avoid setTimeout, setInterval;
  • Avoid changing the style of each frame with jQuery animate()-style. Using CSS to declare animations will result in better browser optimization. Using Translate instead of Absolute positioning results in better FPS and smoother animation.

Take advantage of hardware capabilities, such as enabling GPU acceleration through 3D deformation

In Chrome, 3D or perspective transform CSS properties and animating opacity CSS will create new layers. Under the optimization of hardware-accelerated rendering channel, after the GPU completes 3D deformation and other operations, Compesite Layers to avoid triggering large redraws and rearrangements in the browser.

Note: 3D deformation will consume more memory and power consumption.

Moving 500px right with translate3D is much better than moving left directly:

.ball-1 { transition: -webkit-transform .5s ease; -webkit-transform: translate3d(0, 0, 0); } .ball-1.slidein{ -webkit-transform: translate3d(500px, 0, 0); } .ball-2 { transition: left .5s ease; Left: 0; }.ball-2. Slidein {left: 500px; }Copy the code

Improve CSS selector performance

The performance impact of CSS selectors comes from the time it takes for the browser to match the selectors and document elements, so the principle of optimizing selectors is to avoid using selectors that consume more matching time. To do this, we need to understand the CSS selector matching mechanism, such as the child selector rule:

#header > a {font-weight:blod; }
Copy the code

Most of us read from left to right, so we habitually set our browsers to match rules from left to right, presumably without much overhead.

We’ll assume that the browser works by looking for an element whose ID is header, and then applying the style rule to the A element in the immediate child element. We know that there is only one element with the ID header in the document, and that it has only a few child nodes of the A element, so this CSS selector should be pretty efficient.

Instead, CSS selectors match rules from right to left. Knowing this mechanism, the seemingly efficient selector in the example is expensive to match in practice, and the browser must traverse all the A elements in the page and determine whether the parent element’s ID is header.

It would be more expensive to change the example’s child selector to a descendant selector, traversing all the A elements in the page up to the root node.

#header  a {font-weight:blod;}
Copy the code

Once you understand how CSS selectors match from right to left, you understand that as long as there are other selectors to the left of the current selector, the style system will continue to move left until it finds a selector that matches the rule, or exits because it doesn’t match. We call the right-most selector a key selector.

  1. Avoid generic selectors
/* not recommended */. Content * {color: red; }Copy the code

The browser matches all elements in the document and then matches each element with class content up to the root node of the document. Therefore, the matching overhead is very high, so avoid the case where the key selector is a wildcard selector.

  1. Avoid limiting id selectors with labels or class selectors
/* not recommended */ button# backButton {... }Recommend * / / *# newMenuIcon {... }
Copy the code
  1. Avoid using labels to restrict class selectors
/* Not recommended */ treecell.indented {... } /* Recommended */.treecell-indented {... }.hierarchy-deep {... }Copy the code
  1. Avoid using multiple label selectors. Use class selector instead to reduce CSS lookups
/* Not recommended */ treeItem [mailFolder ="true"] > treerow > treecell {... } /* Recommended */.treecell-mailFolder {... }Copy the code
  1. Avoid using child selectors
Treehead treerow treecell {... Treehead > treerow > treecell {... } /* more recommended */.treecell-header {... }Copy the code
  1. Using inheritance
/* not recommended */#bookmarkMenuItem > .menu-left { list-style-image: url(blah) }Recommend * / / *#bookmarkMenuItem { list-style-image: url(blah) }
Copy the code

JavaScript

General agreement

annotation

The principle of

  • As short As possible (if not necessary, don’t add comments) : Improve the clarity and readability of the code itself;
  • As long As necessary: Proper comments, typography, etc., can make your code more readable and aesthetically pleasing.

Single-line comments

A row must be exclusive. // Followed by a space, indented to match the next line of commented code.

Multiline comment

Avoid using /… / Multiline comments like this. Use multiple single-line comments when you have multi-line comment content.

Function/method comments

  1. Function/method comments must contain the description of the function and must be identified with comments if there are arguments and return values;
  2. Parameter and return value annotations must contain type information and description;
  3. You can use the @inner identifier when the function is internal and not externally accessible.
@param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=} @param {number=returnObject} Return value Description */function foo(p1, p2, p3) {
    var p3 = p3 || 10;
    return {
        p1: p1,
        p2: p2,
        p3: p3
    };
}
Copy the code

File comment

File comments are used to tell readers unfamiliar with the code what is contained in the file. You should provide the general content of the file, its author, dependencies, and compatibility information. As follows:

/**
 * @fileoverview Description of file, its uses and information
 * about its dependencies.
 * @author [email protected] (Firstname Lastname)
 * Copyright 2009 Meizu Inc. All Rights Reserved.
 */
Copy the code

named

Variables, using Camel nomenclature.

var loadingModules = {};
Copy the code

Private properties, variables, and methods begin with an underscore _.

var _privateMethod = {};
Copy the code

Constants, using all uppercase letters, words separated by underscores.

var HTML_ENTITY = {};
Copy the code

Function, using Camel nomenclature.

Function parameters, using Camel nomenclature.

function stringFormat(source) {}

function hear(theBells) {}
Copy the code

Class, using Pascal nomenclature.

Class methods/attributes, using Camel nomenclature.

function TextNode(value, engine) {
    this.value = value;
    this.engine = engine;
}

TextNode.prototype.clone = function () {
    return this;
};
Copy the code

Enumeration variables use Pascal nomenclature.

Properties of enumerations, with all uppercase letters and underscore separated names between words.

var TargetState = {
    READING: 1,
    READED: 2,
    APPLIED: 3,
    READY: 4
};
Copy the code

A multi-word abbreviation in which the case of all letters is the same as the case of the first letter, depending on the current nomenclature and where it occurs.

function XMLParser() {}

function insertHTML(element, html) {}

var httpRequest = new HTTPRequest();
Copy the code

Naming the grammar

Class names, using nouns.

function Engine(options) {}
Copy the code

The function name, using a verb-object phrase.

function getStyle(element) {}
Copy the code

Boolean variables start with is or has.

var isReady = false;
var hasMoreCommands = false;
Copy the code

Promise objects are expressed in the continuous tense of the verb-object phrase.

var loadingData = ajax.get('url');
loadingData.then(callback);
Copy the code

Interface naming conventions

  1. Readable, see the name of xiaoyi;
  2. Try not to conflict with existing customs of Vue, React, jQuery, etc.
  3. Write as much as you can. Do not abbreviate, except as agreed in the list below (the variable aims for clarity, and Uglify does the volume compression).
Common words instructions
options Options, consistent with jQuery community, do not use config, opts, etc
active Do not use current, etc
index Index, do not use IDX, etc
trigger Contact elements
triggerType Trigger type and mode
context Represents the passed this object
object It is recommended to write in full, not recommended to abbreviate o, obj, etc
element It is recommended to write in full, but not recommended to abbreviate el, ELEm, etc
length Don’t write len, l
prev The abbreviation of previous
next Next to the next
constructor I can’t write cTOR
easing Shows the animation smoothing function
min Minimize the abbreviation of
max Maximize the abbreviation of
DOM Don’t write dom, DOM
.hbs Use the HBS suffix for templates
btn The abbreviation of the button
link hyperlinks
title The main text
img Image path (img tag SRC attribute)
dataset Html5 data-XXX data interface
theme The theme
className The name of the class
classNameSpace Class namespace
. .

Boolean expressions True and False

Typeof is preferred for type detection. Object type detection uses Instanceof. Null or undefined is detected using == null.

The following Boolean expressions all return false:

  • null
  • undefined
  • “Empty string
  • 0 0

But beware of the following, which all return true:

  • ‘0’ string 0
  • [] an empty array
  • An empty object {}

Do not use for-in loops on arrays

The for-In loop is only used for object/map/hash traversal. The for-in loop for Array sometimes causes errors. Because it doesn’t iterate from 0 to Length-1, it’s all the keys that appear in the object and its prototype chain.

// Not recommended
function printArray(arr) {
  for (var key in arr) {
    print(arr[key]); }}printArray (,1,2,3 [0]); // This works. var a = new Array(10);printArray(a);  // This is wrong.

a = document.getElementsByTagName(The '*');
printArray(a); A = [0,1,2,3]; a.buhu ='wine';
printArray(a);  // This is wrong again.

a = new Array;
a[3] = 3;
printArray(a);  // This is wrong again.

// Recommended
function printArray(arr) {
  var l = arr.length;
  for (var i = 0; i < l; i++) {
    print(arr[i]); }}Copy the code

Binary and ternary operators

Operators are always written on the previous line to avoid unintended problems with implicit insertion of semicolons.

Var x = a? b : c; Var y = a? longButSimpleOperandB : longButSimpleOperandC; var z = a ? moreComplicatedB : moreComplicatedC;Copy the code

The same is true for the. Operator:

var x = foo.bar().
    doSomething().
    doSomethingElse();
Copy the code

The conditional (ternary) operator (? 🙂

Ternary operators are used instead of if conditional statements.

/ / do not recommendif(val ! = 0) {return foo();
} else {
  returnbar(); } / / recommendationsreturn val ? foo() : bar();
Copy the code

&& and | |

The binary Boolean operator is short-circuited and evaluates to the last term only if necessary.

/ / do not recommendfunction foo(opt_win) {
  var win;
  if (opt_win) {
    win = opt_win;
  } else {
    win = window;
  }
  // ...
}

if (node) {
  if (node.kids) {
    if(node.kids[index]) { foo(node.kids[index]); }}} // Recommendedfunction foo(opt_win) {
  var win = opt_win || window;
  // ...
}

var kid = node && node.kids && node.kids[index];
if (kid) {
  foo(kid);
}
Copy the code

Performance optimization

Little-known DOM

Slow DOM performance can be attributed to the following three reasons:

  • Large scale DOM manipulation
  • Scripts trigger too much refactoring and redrawing
  • The path of the node in the DOM is slow

The solution

  1. Minimize the number of DOM operations

Browser traversal of DOM elements is expensive. The easiest way to optimize DOM tree queries is to save an element in a variable when it appears more than once, avoiding multiple queries to the DOM tree.

Var myList = //"";
var myListHTML = document.getElementById("myList").innerHTML;

for (var i = 0; i < 100; i++) {
  myList += "<span>" + i + "</span>"; } myListHTML = myList; / / do not recommendfor (var i = 0; i < 100; i++) {
  document.getElementById("myList").innerHTML += "<span>" + i + "</span>";
}
Copy the code

Frameworks such as Vue and React use the Diff algorithm.

  1. Avoid unnecessary backflow redraw (CSS performance tuning mentioned)

eval && try-catch-finally

eval

Whenever possible, avoid using the eval method, as it can be expensive to perform.

Using eval or function constructor adds overhead because every time a script engine calls them they must convert the source code into executable code;

Also, with eval, the string is broken during execution.

try-catch-finally

Do not use try-catch-finally where performance is heavily affected.

When you are not sure whether this method will succeed, try-catch is recommended to avoid blocking the current code.

Cache array length

Looping is definitely a very relevant part of JavaScript performance. By storing the length of the array, you can effectively avoid recalculating each loop.

Note: While modern browser engines optimize this process automatically, don’t forget about older browsers.

var arr = new Array(1000), len, i; // Recommended - The length is calculated only once and stored in lenfor(i = 0, len = arr.length; i < len; I++) {} // not recommended - the length needs to be computed every timefor (i = 0; i < arr.length; i++) {

}
Copy the code

Asynchronously load third-party content

When you can’t guarantee that embedding third-party content like a Youtube video or a like/ Tweet button will work, consider asynchronous loading of this code to avoid blocking the entire page load.

(function() {

    var script,
        scripts = document.getElementsByTagName('script') [0];function load(url) {
      script = document.createElement('script');
      script.async = true;
      script.src = url;
      scripts.parentNode.insertBefore(script, scripts);
    }

    load('//apis.google.com/js/plusone.js');
    load('//platform.twitter.com/widgets.js');
    load('//s.widgetsite.com/widget.js'); } ());Copy the code

Avoid using jQuery for animations

Do not use slideUp/Down() fadeIn/fadeOut() methods. Try not to use the animate() method.

HTTP optimization

  1. Reducing HTTP requests
  • Merge files, such as CSS code and JS code into one CSS file and JS file respectively
  • Use CSS Sprite, refer to the CSS Sprite section of CSS optimization for details (HTTP2.0 Sprite advantage no longer exists)
  • Use Base64 technology
  1. Redirection optimization
  • Eliminate unnecessary jumps
  • Leverage the server to override links that the user types
  • Use HTTP instead of JS or META for redirection
  1. Avoid dead/empty /404/410 errors
  • Avoid 404 Not Found errors
  • Avoid image request empty link (img.src= “”)
  1. As soon as possible flush buffer
  • Early use of Flush Buffer improves the user experience by allowing some content to load first
  1. Character Settings in HTTP
  • Specify content-type and the correct character encoding

Cache optimization

  1. Browser cache

Add the Expires or cache-control header

  • For static resources: “Never expire” by setting a far expiration time

  • For dynamic resources: Use an appropriate cache-control header to help the browser Control the request

    Browsers use caching to reduce the number and size of HTTP requests and make pages load faster. Web servers use the Expires header in HTTP responses to tell clients how long a resource can be cached. Note that if you use an “Expires” header, you must change the name of the resource at the same time it changes. This technique improves page performance based on the fact that users have already visited your site.

  • Set the last-modified date to the Last time the resource needed to change

Using “identity” for dynamically available caches

Change the cache by linking to a unique URL to a resource that changes its filename each time it changes

Set the Vary header for IE

Avoid cache conflicts caused by urls in Firefox

Firefox stores a cache of urls in hash tables, but the hash value is only 8 characters long and can cause hash collisions, so you need to make sure your resource URLDIff is larger than the 8 character boundary.

  1. Proxy server (static resource server) cache

The cache-Control: public header allows resources to be cached on a Web proxy server for use by other users.

  • Do not append query strings to static resource urls
  • Resources with cookies set are not cached on the proxy server
  • Be aware of using proxies to cache JS and CSS files

DNS

  1. Reducing DNS resolution
  • Fixed URL provides resources
  • As far as possible the use of the URL path instead of host names such as developer.example.com can be replaced by www.example.com/developer. Unless there is a technical reason for a different host name.
  • Serve the js files that need to be loaded first from the same host domain name as the main file
  • Consider using DNS preresolution
  1. Add a static resource domain name
  • Realize the parallel downloading of multiple resources

Server load optimization

  1. Use CNDS

CDN can help users get the required resources more quickly.

  1. Cookie optimization
  • The server side store is used to do the payload for most cookies: storing the key in the cookie and the value on the server side.
  • Removes unused or duplicate cookies
  • Do not include cookies in static resource requests
  • Do not load js that need to be loaded in advance into fields without cookies
  1. Using Gzip

Gzip is currently the most popular and effective compression method.

  • In HTTP /1.1, Web clients explicitly support accept-Encoding: gzip, deflate compression in the accept-encoding header of HTTP requests
  • Gzip typically reduces the size of server response files by 70% and is supported by 90% of browsers
  • Servers select gzip compression based on file type, and many web sites gzip their HTML files, as well as scripts and stylesheets
  • In fact, any response text, including XML and JSON, has compression value, images and PDF files should not be giZP because they are already compressed
  1. The compressed file

Compression includes Javascript, CSS, and HTML

To make your pages more efficiently compressed:

  • Specify the CSS key pairs in alphabetical order
  • Specify HTML attributes in alphabetical order
  • Use consistent quotes for HTML attributes
  • Use consistent letters (lowercase)
  • Remove unused CSS

Image correlation optimization

  1. Image compression: Use PNG8 format whenever possible
  2. Image zooming: The server zooms in and out images

Vue code specification

Necessary (error avoidance)

Component names are multiple words

Component names should always be multiple words, except for the root component App and Vue built-in components like
and < Component >.

This avoids conflicts with existing and future HTML elements because all HTML element names are single words.

/ / counterexample ponent (Vue.com'todo'{/ /... })export default {
  name: 'Todo',
  // ...
}
Copy the code
// Vue.component('todo-item'{/ /... })export default {
  name: 'TodoItem',
  // ...
}
Copy the code

The component data

The component’s data must be a function.

When a data property is used in a component (anywhere but new Vue), its value must be a function that returns an object.

/ / counterexample ponent (Vue.com'some-comp', {
  data: {
    foo: 'bar'}})export default {
  data: {
    foo: 'bar'}}Copy the code
// Vue.component('some-comp', {
  data: function () {
    return {
      foo: 'bar'
    }
  }
})
// In a .vue file
export default {
  data () {
    return {
      foo: 'bar'}}} // It is ok to use objects directly on the root instance of a Vue, since only one such instance exists. new Vue({ data: { foo:'bar'}})Copy the code

Prop definition

Prop definitions should be as detailed as possible.

In your submitted code, the definition of prop should be as detailed as possible, or at least specify its type.

// Counterexample // This is acceptable only when developing prototype systems: ['status']
Copy the code
// Props: {status: String} props: { status: {type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing'.'synced'.'version-conflict'.'error'].indexOf(value) ! == -1}}}Copy the code

Set the key value for V-for

Always use a key with v-for.

A key must always be used with v-FOR on a component to maintain the state of the internal component and its subtrees. Even maintaining predictable behavior on elements, such as object constancy in animation, is a good practice.

<ul> <li v-for="todo in todos">
    {{ todo.text }}
  </li>
</ul>
Copy the code
<ul> <li v-for="todo in todos"
    :key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>
Copy the code

Avoid v-if and V-for

Never use v-if and V-for on the same element.

We tend to do this in two common situations:

To filter items in a list (for example, v-for=”user in users” v-if=” user.isactive “). In this case, replace Users with a calculated property (such as activeUsers) and have it return the filtered list.

To avoid rendering lists that should be hidden (such as v-for=”user in users” v-if=”shouldShowUsers”). In this case, move the V-if to the container element (such as ul, OL).

<ul> <li v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
<ul>
  <li
    v-for="user in users"
    v-if="shouldShowUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
Copy the code
<ul> <li v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
Copy the code

Set the scope for the component style

Styles in top-level App components and layout components can be global to an application, but all other components should be scoped.

This rule applies only to single-file components. You don’t have to use scoped attributes. You can also set scopes through CSS Modules, which is a class-based beM-like strategy, but you can also use other libraries or conventions.

However, for component libraries, we should prefer class-based policies to Scoped attributes.

This makes it easier to override internal styles: it uses a class name that people can understand, doesn’t have too high a selector priority, and is less likely to cause conflicts.

<template> <button class="btn btn-close">X</button>
</template>

<style>
.btn-close {
  background-color: red;
}
</style>
Copy the code
<template> <button class="button button-close">X</button> </template> <! <style scoped>. Button {border: none; border-radius: 2px; } .button-close { background-color: red; } </style> <template> <button :class="[$style.button, $style.buttonClose]">X</button> </template> <! <style module>. Button {border: none; border-radius: 2px; } .buttonClose { background-color: red; } </style> <template> <button class="c-Button c-Button--close">X</button> </template> <! <style>. C -Button {border: none; border-radius: 2px; } .c-Button--close { background-color: red; } </style>Copy the code

Private property name

Use module scopes to keep functions that are not externally accessible private. If this is not possible, always use custom private properties for plugins, mixins, and so on without considering them as external public apisyourPluginName).

Var myGreatMixin = {//... methods: { update:function() {/ /... } } } var myGreatMixin = { // ... methods: { _update:function() {/ /... } } } var myGreatMixin = { // ... methods: {$update: function() {/ /... } } } var myGreatMixin = { // ... methods: {$_update: function() {/ /... }}}Copy the code
Var myGreatMixin = {//... methods: {$_myGreatMixin_update: function() {/ /... }}} // Even better! var myGreatMixin = { // ... methods: {publicMethod() {/ /... myPrivateFunction() } } }function myPrivateFunction() {/ /... }export default myGreatMixin
Copy the code

Highly recommended (for readability)

Component files

As long as there is a build system that can concatenate files, separate each component into a file.

When you need to edit a component or look up its usage, you can find it more quickly.

/ / counterexample ponent (Vue.com'TodoList'{/ /... }) Vue.component('TodoItem'{/ /... })Copy the code
Good example / / components / | - TodoList. Js | - TodoItem. Js components / | - TodoList. Vue | - TodoItem. VueCopy the code

The case of a single-file component file

The filename of a single-file component should always be either uppercase (PascalCase) or horizontal (kebab-case).

Uppercase is the most friendly for code editor auto-completion, because it makes it as consistent as possible in the way we reference components in JS(X) and templates. However, mixing file naming can sometimes lead to problems with case-insensitive file systems, which is why horizontal join naming is also perfectly desirable.

/ / counterexample components / | - mycomponent. Vue components / | - mycomponent. VueCopy the code
Good example / / components / | - MyComponent. Vue components / | - my - component. VueCopy the code

Base component name

Underlying components that apply specific styles and conventions (that is, components that present classes without logic or stateless) should all start with a specific prefix, such as Base, App, or V.

/ / counterexample components / | - MyButton. Vue | - VueTable. Vue | - Icon. VueCopy the code
Good example / / components / | - BaseButton. Vue | - BaseTable. Vue | - BaseIcon. Vue components / | - AppButton. Vue | - AppTable. Vue | - AppIcon.vue components/ |- VButton.vue |- VTable.vue |- VIcon.vueCopy the code

Singleton component name

Components that should only have a single active instance should be named with The prefix to indicate their uniqueness.

This does not mean that components can only be used on a single page, but only once per page. These components never accept any prop because they are customized for your application, not their context in your application. If you find it necessary to add prop, that means it is actually a reusable component that is currently only used once per page.

/ / counterexample components / | - Heading. Vue | - MySidebar. VueCopy the code
Good example / / components / | - TheHeading. Vue | - TheSidebar. VueCopy the code

Tightly coupled component name

Child components that are tightly coupled to the parent component should be named prefixed with the parent component name.

If a component only makes sense in the context of a parent component, this relationship should be reflected in its name. Because editors usually organize files alphabetically, doing so puts related files together.

/ / counterexample components / | - TodoList. Vue | - TodoItem. Vue | - TodoButton. Vue components / | - SearchSidebar. Vue | - NavigationForSearchSidebar.vueCopy the code
Good example / / components / | - TodoList. Vue | - TodoListItem. Vue | - TodoListItemButton. Vue components / | - SearchSidebar. Vue | - SearchSidebarNavigation.vueCopy the code

Order of words in component names

Component names should start with high-level (usually generically described) words and end with descriptive modifiers.

/ / counterexample components / | - ClearSearchButton. Vue | - ExcludeFromSearchInput. Vue | - LaunchOnStartupCheckbox. Vue | - RunSearchButton.vue |- SearchInput.vue |- TermsCheckbox.vueCopy the code
Good example / / components / | - SearchButtonClear. Vue | - SearchButtonRun. Vue | - SearchInputQuery. Vue | - SearchInputExcludeGlob. Vue  |- SettingsCheckboxTerms.vue |- SettingsCheckboxLaunchOnStartup.vueCopy the code

Self-closing assembly

Components that have no content in single-file components, string templates, and JSX should be self-closing — but never in DOM templates.

Self-closing components indicate that they not only have no content, but intentionally have no content. The difference is like a blank page in a book compared to a blank page labeled “this page is intentionally blank.” And without the extra closing tag, your code is much cleaner.

Unfortunately, HTML does not support self-closing custom elements — only official “empty” elements. So the above strategy only applies where Vue’s template compiler can reach before entering the DOM, and then producing HTML that conforms to the DOM specification.

/ / counter example <! -- In single-file components, string templates, and JSX --> <MyComponent></MyComponent> <! --> <my-component/>Copy the code
// Good example <! -- In single-file components, string templates, and JSX --> <MyComponent/> <! <my-component></my-component>Copy the code

Component names in templates are case sensitive

For most projects, component names in single-file components and string templates should always be PascalCase — but always kebab-case in DOM templates.

/ / counter example <! -- in single-file components and string templates --> < myComponent /> <! -- in single-file components and string templates --> <myComponent/> <! </MyComponent> </MyComponent>Copy the code
// Good example <! -- in single-file components and string templates --> <MyComponent/> <! -- In the DOM template --> <my-component></my-component> // or <! <my-component></my-component>Copy the code

Component names in JS/JSX are case sensitive

Component names in JS/JSX should always be PascalCase.

/ / counterexample ponent (Vue.com'myComponent'{/ /... }) import myComponent from'./MyComponent.vue'
export default {
  name: 'myComponent',
  // ...
}
export default {
  name: 'my-component',
  // ...
}
Copy the code
// Vue.component('MyComponent'{/ /... }) Vue.component('my-component'{/ /... }) import MyComponent from'./MyComponent.vue'
export default {
  name: 'MyComponent',
  // ...
}
Copy the code

Full word component name

Component names should tend to be full words rather than abbreviations.

Autocompletion in editors has made writing long names very cheap, and the clarity it provides is invaluable. Infrequently used abbreviations should be avoided in particular.

/ / counterexample components / | - SdSettings. Vue | - UProfOpts. VueCopy the code
Good example / / components / | - StudentDashboardSettings. Vue | - UserProfileOptions. VueCopy the code

Prop name case

When declaring prop, it should always be named camelCase, and kebab-case should always be used in templates and JSX.

// Props: {'greeting-text': String
}
<WelcomeMessage greetingText="hi"/>
Copy the code
// Good example: {greetingText: String} <WelcomeMessage greeting-text="hi"/>
Copy the code

An element with multiple attributes

Elements with multiple attributes should be written in multiple lines, one for each attribute.

In JavaScript, it is a common best practice to separate multiple properties of objects with multiple lines because it is easier to read. Templates and JSX deserve the same consideration.

<img SRC = <img SRC ="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/5/171e32206dd8edfa~tplv-t2oaga2asx-image.image" alt="Vue Logo">
<MyComponent foo="a" bar="b" baz="c"/>
Copy the code
<img SRC = "img SRC ="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/5/171e32206dd8edfa~tplv-t2oaga2asx-image.image"
  alt="Vue Logo"
>
<MyComponent
  foo="a"
  bar="b"
  baz="c"
/>
Copy the code

Simple expressions in templates

Component templates should contain only simple expressions, and complex expressions should be refactored to evaluate properties or methods.

Complex expressions can make your templates less declarative. We should try to describe what should happen, not how to calculate that value. And evaluating properties and methods makes code reusable.

// counterexample {{fullname.split (' ').map(function (word) {
    return word[0].toUpperCase() + word.slice(1)
  }).join(' ')}}Copy the code
// Good example <! -- In the template --> {{normalizedFullName}} // Complex expressions have been moved to a computed attribute computed: {normalizedFullName:function () {
    return this.fullName.split(' ').map(function (word) {
      return word[0].toUpperCase() + word.slice(1)
    }).join(' ')}}Copy the code

Simple calculation properties

Complex computed properties should be split into as many simpler properties as possible.

// Counter example computed: {price:function () {
    var basePrice = this.manufactureCost / (1 - this.profitMargin)
    return (
      basePrice -
      basePrice * (this.discountPercent || 0)
    )
  }
}
Copy the code
// Good example computed: {basePrice:function () {
    return this.manufactureCost / (1 - this.profitMargin)
  },
  discount: function () {
    return this.basePrice * (this.discountPercent || 0)
  },
  finalPrice: function () {
    return this.basePrice - this.discount
  }
}
Copy the code

Attribute value with quotation marks

Non-empty HTML attribute values should always have quotes (single or double quotes, whichever you don’t use in JS).

/ / counter example < inputtype=text>
<AppSidebar :style={width:sidebarWidth+'px'} >Copy the code
// Good example <inputtype="text">
<AppSidebar :style="{ width: sidebarWidth + 'px' }">
Copy the code

Instructions for

Instruction abbreviations (: for V-bind:, @ for V-on:, and # for V-slot :).

// Example <input v-bind:value="newTodoText"
  :placeholder="newTodoInstructions"
>
<input
  v-on:input="onInput"
  @focus="onFocus"
>
<template v-slot:header>
  <h1>Here might be a page title</h1>
</template>

<template #footer>
  <p>Here's some contact info</p>
</template>
Copy the code
<input :value="newTodoText"
  :placeholder="newTodoInstructions"
>
<input
  v-bind:value="newTodoText"
  v-bind:placeholder="newTodoInstructions"
>
<input
  @input="onInput"
  @focus="onFocus"
>
<input
  v-on:input="onInput"
  v-on:focus="onFocus"
>
<template v-slot:header>
  <h1>Here might be a page title</h1>
</template>

<template v-slot:footer>
  <p>Here's some contact info

s some contact info</p> </template> Copy the code

Recommendation (to minimize selection and cognitive costs)

Order of component/instance options

Component/instance options should have a uniform order.

  1. Side effects (trigger effects outside the component)
  • el
  1. Global awareness (requires knowledge beyond components)
  • name
  • parent
  1. Component type (Changing the type of the component)
  • functional
  1. Template modifier (changes how templates are compiled)
  • delimiters
  • comments
  1. Template dependencies (resources used within templates)
  • components
  • directives
  • filters
  1. Combine (merge property into options)
  • extends
  • mixins
  1. Interface (component interface)
  • inheritAttrs
  • model
  • props/propsData
  1. Local state (local responsive property)
  • data
  • computed
  1. Events (callbacks triggered by reactive events)
  • watch

  • Lifecycle hooks (in the order in which they are invoked)

    beforeCreate

    created

    beforeMount

    mounted

    beforeUpdate

    updated

    activated

    deactivated

    beforeDestroy

    destroyed

  1. Non-reactive Property (independent of the instance property of the responding system)
  • methods
  1. Render (declarative description of component output)
  • template/render
  • renderError

The order of element attributes

There should be a consistent order of attributes for elements, including components.

  1. Define (provide options for components)
  • is
  1. List rendering (creating multiple variations of the same element)
  • v-for
  1. Conditional rendering (whether the element is rendered/displayed)
  • v-if
  • v-else-if
  • v-else
  • v-show
  • v-cloak
  1. Render (Change how elements are rendered)
  • v-pre
  • v-once
  1. Global awareness (requires knowledge beyond components)
  • id
  1. Unique attribute (attribute that requires a unique value)
  • ref
  • key
  1. Bidirectional binding (combining bindings with events)
  • v-model
  1. Other attributes (all plain bound or unbound attributes)

  2. Events (Component event listeners)

  • v-on
  1. Content (overrides the content of the element)
  • v-html
  • v-text

Blank lines in component/instance options

// Props: {value: {type: String,
    required: true
  },

  focused: {
    type: Boolean,
    default: false
  },

  label: String,
  icon: String
},

computed: {
  formattedValue: function() {/ /... }, inputClasses:function() {/ /... }}Copy the code
// No empty lines are also fine when components are easy to read and navigate. props: { value: {type: String,
    required: true
  },
  focused: {
    type: Boolean,
    default: false
  },
  label: String,
  icon: String
},
computed: {
  formattedValue: function() {/ /... }, inputClasses:function() {/ /... }}Copy the code

The order of the top-level elements of a single-file component

Single-file components should always have the same order of

< span style>/*... */</style> <script>/* ... */</script> <template>... </template> <! -- ComponentA.vue --> <script>/* ... */</script> <template>... </template> <style>/* ... */</style> <! -- ComponentB.vue --> <template>... </template> <script>/* ... */</script> <style>/* ... */</style>Copy the code
// Good example <! -- ComponentA.vue --> <script>/* ... */</script> <template>... </template> <style>/* ... */</style> <! -- ComponentB.vue --> <script>/* ... */</script> <template>... </template> <style>/* ... */</style> <! -- ComponentA.vue --> <template>... </template> <script>/* ... */</script> <style>/* ... */</style> <! -- ComponentB.vue --> <template>... </template> <script>/* ... */</script> <style>/* ... */</style>Copy the code

Use caution (potentially dangerous patterns)

Key is not used in v-if/ V-else -if/ V-else

// counterexample <div v-if="error"> error: {{error}} < / div > < div v - else > {{results}} < / div >Copy the code
<div v-if="error"
  key="search-status"{{error}} </div> <div v-else key="search-results"
>
  {{ results }}
</div>
Copy the code

Element selector in scoped

Element selectors should be avoided in scoped.

In the Scoped style, class selectors are better than element selectors because element selectors are slow to use in large quantities.

<template> <button> </button> </template> <style scoped> button {background-color: red; } </style>Copy the code
<template> <button class="btn btn-close">X</button>
</template>

<style scoped>
.btn-close {
  background-color: red;
}
</style>
Copy the code

Implicit parent-child component communication

Parent component communication should take precedence over this.$parent or changing prop via prop and events.

An ideal Vue application is prop passed down and events passed up. Following this convention will make your components easier to understand. However, changes to prop or this.$parent in some boundary cases can simplify two deeply coupled components.

/ / counterexample ponent (Vue.com'TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },
  template: '<input v-model="todo.text">'
})
Vue.component('TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },
  methods: {
    removeTodo () {
      var vm = this
      vm.$parent.todos = vm.$parent.todos.filter(function (todo) {
        returntodo.id ! == vm.todo.id }) } }, template: ` <span> {{ todo.text }} <button @click="removeTodo">
        X
      </button>
    </span>
  `
})
Copy the code
// Vue.component('TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },
  template: `
    <input
      :value="todo.text"
      @input="$emit('input', $event.target.value)"
    >
  `
})
Vue.component('TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },
  template: `
    <span>
      {{ todo.text }}
      <button @click="$emit('delete')">
        X
      </button>
    </span>
  `
})
Copy the code

Non-flux global state management

Global state should be managed through Vuex in preference to this.$root or a global event bus.

Managing state through this.$root and/or the global event bus is convenient for many simple cases, but not for most applications.

Vuex is the official Flux-like implementation of Vue, which provides not only a central area for managing state, but also a great tool for organizing, tracking, and debugging state changes. It is well integrated into the Vue ecosystem (including full Vue DevTools support).

New Vue({data: {todos: []}, created:function () {
    this.$on('remove-todo', this.removeTodo)
  },
  methods: {
    removeTodo: function (todo) {
      var todoIdToRemove = todo.id
      this.todos = this.todos.filter(function (todo) {
        returntodo.id ! == todoIdToRemove }) } } })Copy the code
// store/modules/todos.jsexportdefault { state: { list: [] }, mutations: { REMOVE_TODO (state, todoId) { state.list = state.list.filter(todo => todo.id ! == todoId) } }, actions: { removeTodo ({ commit, state }, todo) { commit('REMOVE_TODO', todo.id) } } } <! -- TodoItem.vue --> <template> <span> {{ todo.text }} <button @click="removeTodo(todo)">
      X
    </button>
  </span>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },
  methods: mapActions(['removeTodo'])
}
</script>
Copy the code

VSCode + ESLint practices the front-end coding specification

Install the VSCode ESlint extension

First, open the VSCode extension panel and search for the ESLint extension, then click install

Once installed, click reload or exit to reopen the extension to activate it, but for the extension to work, we need to configure ESLint first.

Install ESLint in the project

When you build a project using Vue or React scaffolding, you will be asked whether to install ESLint. If so, simply change the.eslintrc.js file and VSCode ESLint configuration.

Here is the.eslintrc.js configuration in our project:

// http://eslint.org/docs/user-guide/configuring

module.exports = {
  root: true,
  parser: 'babel-eslint',
  parserOptions: {
    sourceType: 'module'
  },
  env: {
    browser: true,
  },
  // https://github.com/standard/standard/blob/master/docs/RULES-en.md
  extends: 'standard',
  // required to lint *.vue files
  plugins: [
    'html'
  ],
  // add your custom rules here
  'rules': {
    // allow paren-less arrow functions
    'arrow-parens': 0,
    // allow async-await
    'generator-star-spacing': 0,
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production'? 2:0},'globals': {
    'moa': true}}Copy the code

If you only want ESLint to be part of your project build system, we can install it locally in the project root directory:

npm install eslint --save-dev
Copy the code

If you want ESLint to work with all your projects, we recommend using a global installation. After using a global installation of ESLint, any ESLint plug-ins or shareable configurations you use must also be installed globally.

Here’s how we use the global installation:

npm install -g eslint
Copy the code

Once installed, we use the eslint –init command to generate a configuration file in the user directory (or anywhere you like)

We choose the custom code style in the first option and then choose it ourselves based on the project needs.

After setting this up we get a configuration file called.eslintrc.js:

Module.exports = {env: {browser:} // Exports = {env:} // exports = {env:} // exports = {env:} // exports = {env:} // exports = {env:} // exports = {env:}true,
    es6: true
  },
  extends: [
    'plugin:vue/essential'.'standard'
  ],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly'
  },
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module'
  },
  plugins: [
    'vue'
  ],
  rules: {
  }
}
Copy the code

Configuring ESLint (Understood)

After the configuration file is generated, you can customize the configuration. Here we only briefly explain the common configuration items. The complete configuration items can be accessed from the official documents

Configure the environment

In the configuration file generated above, you can use the env attribute to specify the environment to be enabled, and set it to true to ensure that code checks do not identify predefined global variables of these environments as undefined variables and report errors:

"env": {
    "browser": true."commonjs": true."es6": true."jquery": true
}
Copy the code

Setting language Options

By default, ESLint supports ECMAScript 5 syntax. If you want to enable support for other versions of ECMAScript, JSX, etc., ESLint allows you to specify JavaScript language options you want to support using the parserOptions property, although you may need to install plugins such as eslint-plugin-React yourself.

"parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module"."ecmaFeatures": {
        "jsx": true}}Copy the code

Configuration rules

In the configuration file above, the “extends”: “XXXXXX” option enables a recommendation rule. Based on the recommendation rule, we can also use rules to create custom rules as required. The first value of each rule represents the error level displayed after the rule is checked:

  • “Off” or 0 – Turns off the rule
  • “Warn” or 1 – treats the rule as a warning
  • “Error” or 2 – treats the rule as an error
"rules": {
    "indent": [
        "error", 4]."linebreak-style": [
        "error"."windows"]."quotes": [
        "error"."single"]."semi": [
        "error"."never"]}Copy the code

A complete list of configurable rules is available at eslint.cn/docs/rules/

The rule marked with √ indicates that the rule is recommended.

VSCode sets the ESLint extension

After installing and configuring ESLint, go back to VSCode for extension Settings and go to file > preferences > Settings to open the VSCode configuration file.

As you can see from the figure, the ESLint extension is enabled by default, we now just need to add a configuration in settings.json to specify the path to the.eslintrc.js configuration file we created to enable custom rule detection, and ESLint will look for and automatically read them:

"eslint.options": {
    "configFile": "./.eslintrc.js"
},
Copy the code

At this point, we are ready to use the ESLint extension to detect our JS files.

Make ESLint support Vue single-file components

Since ESLint only supports script detection for JS files by default, if we need to support inline script detection for HTMl-like files such as Vue, we also need to install the ESlint-plugin-HTML plugin.

Since we installed ESLint globally, the eslint-plugin-html plugin must also be installed globally:

 npm install -g eslint-plugin-html
Copy the code

After the installation is complete, we go back to file > Preferences > Settings and modify the Settings in Settings and save:

"eslint.options": {
    "configFile": "./.eslintrc.js"."plugins": ["html"]},"eslint.validate": [
    "javascript"."javascriptreact"."html"."vue"
]
Copy the code

Git submission specification

In multi-person collaborative projects, if Git’s submission instructions are accurate, it will become documented in the later collaboration and Bug handling. The development of the project can quickly generate development logs according to the specification of the submission instructions, so as to facilitate the developers or users to track the development information and features of the project. Below are the Vue project submission instructions:

It is difficult to avoid errors when writing compliant submission instructions by hand, and tools are available to implement the specification.

Specification of Git commit instructions

  • Provides more historical information for quick browsing
  • You can filter certain commits to filter code review
  • You can trace commit to generate update logs
  • Can associate issues

Git commit description structure

Git submission instructions can be divided into three sections: Header, Body, and Footer.

<Header> <Body> <Footer>
Copy the code

Header

The Header section contains three fields type (required), Scope (optional), and subject (required).

<type>(<scope>): <subject>
Copy the code

type

Type indicates the commit nature of the commit.

value describe
feat Add a new feature
fix Fix a Bug
docs Document change
style Code formatting (does not affect functionality, such as space, semicolon, and other formatting fixes)
refactor Code refactoring
perf To improve the performance
test test
build Changing project builds or external dependencies (e.g. scopes: webpack, gulp, NPM, etc.)
ci Change the scripts commands in the continuous integration software configuration files and packages, such as scopes: Travis, Circle, etc
chore Change the build process or assistive tools
revert Code back

scope

Scope Indicates the scope of the commit impact. Scope is determined by project. For example, it can be divided by menu or function module in business project, or component library development.

Hint: scope can be omitted.

subject

Subject is a short description of a commit.

Body

A detailed description of the commit, which describes the detailed description of the code commit.

Footer

Footer is required if the code commit is an incompatible change or close defect, otherwise it can be omitted.

Incompatible change

If the current code is incompatible with the previous version, the Footer begins with BREAKING CHANGE, followed by a description of the CHANGE, the reason for the CHANGE, and the migration method.

Close the defect

If the current submission is for a specific issue, you can fill in the Footer section for a single issue or series of issues to close.

Commitizen

Commitizen/CZ – CLI is a tool that can implement normative submission instructions:

Provides selected submission information categories to quickly generate submission instructions.

Install the CZ tool:

npm install -g commitizen
Copy the code

Commitizen adapter

cz-conventional-changelog

If you need to use Commitizen in your project to generate submission instructions that comply with AngularJS specifications, initialize the CZ-Xconventional – Changelog adapter:

commitizen init cz-conventional-changelog --save --save-exact
Copy the code

If another adapter is already in use, the following error is reported, in which case you can initialize it again with the –force option

Error: A previous adapter is already configured. Use --force to override
Copy the code

The initialization command does three things:

  1. Install the CZ-Xcom – Changelog adapter dependency in the project
  2. Save adapter dependencies to the devDependencies field information in package.json
  3. The config.commitizen field is added in package.json, which is used to configure the adapter path of the CZ tool
"devDependencies": {
 "cz-conventional-changelog": "^ 2.1.0." "
},
"config": {
  "commitizen": {
    "path": "./node_modules/cz-conventional-changelog"}}Copy the code

Git cz commit git cz commit git

After the code is submitted remotely, it can be viewed in the corresponding project:

cz-customizable

If you want to customize the submission specification of your project, you can use the CZ-Customizable adapter:

Install adapter

npm install cz-customizable --save-dev
Copy the code

Change the previously Angular compliant CZ-Xconventional – Changelog adapter path to CZ-Customizable adapter path:

"devDependencies": {
  "cz-customizable": "^ 5.3.0." "
},
"config": {
  "commitizen": {
    "path": "node_modules/cz-customizable"}}Copy the code

A.cz-config.js sample file is provided as follows:

'use strict';

module.exports = {

  types: [
    {value: 'feat',     name: 'feat: A new feature'},
    {value: 'fix',      name: 'fix: A bug fix'},
    {value: 'docs',     name: 'docs: Documentation only changes'},
    {value: 'style',    name: 'style: Changes that do not affect the meaning of the code\n (white-space, formatting, missing semi-colons, etc)'},
    {value: 'refactor', name: 'refactor: A code change that neither fixes a bug nor adds a feature'},
    {value: 'perf',     name: 'perf: A code change that improves performance'},
    {value: 'test',     name: 'test: Adding missing tests'},
    {value: 'chore',    name: 'chore: Changes to the build process or auxiliary tools\n and libraries such as documentation generation'},
    {value: 'revert',   name: 'revert: Revert to a commit'},
    {value: 'WIP',      name: 'WIP: Work in progress'}
  ],

  scopes: [
    {name: 'accounts'},
    {name: 'admin'},
    {name: 'exampleScope'},
    {name: 'changeMe'}
  ],

  // it needs to match the value for field type. Eg.: 'fix'
  /*
  scopeOverrides: {
    fix: [
      {name: 'merge'},
      {name: 'style'},
      {name: 'e2eTest'},
      {name: 'unitTest'}
    ]
  },
  */
  // override the messages, defaults are as follows
  messages: {
    type: 'Select the type of change that you\'re committing:', scope: '\nDenote the SCOPE of this change (optional):', // used if allowCustomScopes is true customScope: 'Denote the SCOPE of this change:', subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n', body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n', breaking: 'List any BREAKING CHANGES (optional):\n', footer: 'List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n',
    confirmCommit: 'Are you sure you want to proceed with the commit above? '
  },

  allowCustomScopes: true,
  allowBreakingChanges: ['feat'.'fix'], / /limit subject length
  subjectLimit: 100
  
};
Copy the code

Here it is rendered in Chinese (just to illustrate an example of a custom specification) :

'use strict';

module.exports = {

  types: [
    {value: 'properties',     name: 'Features: A new feature'},
    {value: 'repair',      name: '修复:    修复一个Bug'},
    {value: 'document',     name: 'Documentation: Only documentation changes'},
    {value: 'format',    name: 'Formatting: Spaces, semicolons and other formatting fixes'},
    {value: 'reconstruction', name: 'Refactoring: Code refactoring, separate from features and fixes'},
    {value: 'performance',     name: 'Performance: Improve performance'},
    {value: 'test',     name: 'Tests: Add a test'},
    {value: 'tools',    name: 'Tools: Development tool changes (build, scaffolding tools, etc.)'},
    {value: 'the rollback',   name: 'Rollback: Code rollback'}
  ],

  scopes: [
    {name: 'module 1'},
    {name: '2'},
    {name: 'module 3'},
    {name: 'module 4'}
  ],

  // it needs to match the value for field type. Eg.: 'fix'
  /*
  scopeOverrides: {
    fix: [
      {name: 'merge'},
      {name: 'style'},
      {name: 'e2eTest'},
      {name: 'unitTest'}
    ]
  },
  */
  // override the messages, defaults are as follows
  messages: {
    type: 'Choose one of your submission types :',
    scope: Select a scope (optional):,
    // used if allowCustomScopes is true
    customScope: 'Denote the SCOPE of this change:',
    subject: 'Short note :\n',
    body: 'long, the use of "|" newline (optional) : \ n',
    breaking: 'Incompatibility notes (Optional):\n',
    footer: 'Associate closed issues, e.g. : #31, #34(optional):\n',
    confirmCommit: 'Sure about the submission instructions? '
  },

  allowCustomScopes: true,
  allowBreakingChanges: ['properties'.'repair'], / /limit subject length
  subjectLimit: 100

};

Copy the code

Git cz git cz

It can be seen from the above figure that the submission instruction option has been Translated into Chinese. Continue to fill in the submission instruction:

To submit code to remote:

Commitizen check (Understand)

commitlint

Verify that the submission instructions comply with the specification, install the validation tool CommitLint:

npm install --save-dev @commitlint/cli
Copy the code

@commitlint/config-conventional

  • Install Angular style validation rules
npm install --save-dev @commitlint/config-conventional 
Copy the code
  • Create a new commitlint.config.js file in your project and set the validation rules:
module.exports = {
  extends: ['@commitlint/config-conventional']};Copy the code
  • Install huksy (Git hook)
npm install husky --save-dev
Copy the code
  • Configure git commit validation hooks in package.json:
"husky": {
  "hooks": {
    "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"}}Copy the code

It is important to note that this validation rule cannot be used to customize.cz-config.js that does not conform to the Angular specification, such as the previous Sinicization. The.cz-config.js file needs to be changed to the official sample file cz-config-example.js in Angular style.

Commitlint needs to configure a check rule. @commitlint/ config-Conventional is a check rule that complies with the Angular specification.

commitlint-config-cz

Commitlint/Config-Conventional if you use the CZ-Customizable adapter, you cannot use the @commitLint/Config-Conventional rule to commit directives that break Angular style. You can verify custom commit instructions using commitlint-config-cz.

  • Installation check rule
npm install commitlint-config-cz --save-dev
Copy the code
  • Commitlint verification rule configuration:
module.exports = {
  extends: [
    'cz']};Copy the code

The @commitlint/ config-Conventional validation rule is recommended. If you want to use the CZ-Customizable adapter, then the custom configuration does not break the Angular specification.

validate-commit-msg

In addition to using the Commitlint validation tool, you can also use the validate-committ-msg validation tool to verify that the CZ commit specification complies with the Angular specification.

Commitizen Log (Understand)

If you use the CZ tool set, supporting Xconventional – Changelog can quickly generate development logs:

npm install conventional-changelog -D
Copy the code

Add the log generation command to package.json:

"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
Copy the code

After running the NPM run version command, you can view the production log Changelog.md.

Ensure that the Header type is correct; otherwise, the generated logs may be inaccurate.

Vue project Code Review standard

V-if and V-show are used in different scenarios

V-if is true conditional rendering because it ensures that event listeners and subcomponents within the conditional block are properly destroyed and rebuilt during the switch; Also lazy: if the condition is false during the initial render, nothing is done — the conditional block does not start rendering until the condition is true for the first time.

V-show is much simpler. Regardless of the initial conditions, elements are always rendered and simply switched based on the display property of CSS.

Therefore, V-IF is suitable for scenarios where conditions are rarely changed at runtime and do not need to be switched frequently; V-show is suitable for scenarios that require very frequent switching of conditions.

Computed and Watch distinguish usage scenarios

Computed: Computed attributes depend on other attribute values, and computed values are cached. Only when the dependent attribute values change, computed values will be recalculated the next time it obtains computed values.

Watch: It is more of a function of “observation”, similar to the listening callback of some data. Whenever the monitored data changes, the callback will be executed for subsequent operations.

Application scenario:

  • When we need to do numerical calculations and rely on other data, we should use computed, because we can take advantage of the caching nature of computed and avoid recalculating each time we get a value.
  • Watch should be used when we need to perform asynchronous or expensive operations when data changes. Using the Watch option allows us to perform asynchronous operations (accessing an API), limits how often we perform that operation, and sets the intermediate state until we get the final result. These are all things you can’t do with computed properties.

Long list performance optimization

Vue hijacks data via Object.defineProperty to make the view respond to data changes. However, sometimes our component is purely a data presentation and nothing will change. We don’t need Vue to hijack our data. This significantly reduces component initialization time, so how do we prevent Vue from hijacking our data? Freeze can be used to freeze an Object. Once the Object is frozen, it cannot be modified.

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users"); this.users = Object.freeze(users); }};Copy the code

V-for traversal must add a key to the item and avoid using v-if at the same time

  1. V-for traversal must add a key to the item

During the traversal rendering of list data, a unique key value should be set for each item to facilitate the accurate finding of the list data by vue.js internal mechanism. When state is updated, the new state value is compared to the old state value to locate the DIFF faster.

  1. V-for traversal avoids using v-if simultaneously

V-for has a higher priority than V-if, and if you need to traverse the entire array every time, it will affect speed, especially if you need to render a small part of it. Replace this with a computed attribute if necessary.

Recommendation:

<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id">
    {{ user.name }}
  </li>
</ul>
computed: {
  activeUsers: function () {
    return this.users.filter(function (user) {
	 return user.isActive
    })
  }
}
Copy the code

Is not recommended:

<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id">
    {{ user.name }}
  </li>
</ul>
Copy the code

Destruction of events

When a Vue component is destroyed, it automatically cleans up its connections to other instances and unties all its instructions and event listeners, but only for the component’s own events. If addEventListener is used in js, it will not be automatically destroyed. We need to manually remove the listener of these events when the component is destroyed to avoid memory leaks. For example:

created() {
  addEventListener('click', this.click, false)},beforeDestroy() {
  removeEventListener('click', this.click, false)}Copy the code

Timer clearing

If the use of a global timer is not necessary, be sure to remove the timer when leaving the current component to avoid memory leaks.

Lazy loading of image resources

For pages with too many pictures, in order to accelerate the loading speed of the page, we need to not load the pictures that do not appear in the visual area of the page, and then load them after scrolling to the visual area. This will greatly improve page loading performance and improve the user experience. We used Vue’s vuE-Lazyload plugin in the project:

  1. Installing a plug-in
npm install vue-lazyload --save-dev
Copy the code
  1. Imported and used in the entry file man.js
import VueLazyload from 'vue-lazyload'
Copy the code
  1. Used in the Vue
Vue.use(VueLazyload)
Copy the code
  1. Or add custom options
Vue.use(VueLazyload, {preLoad: 1.3, error:'dist/error.png',
    loading: 'dist/loading.gif',
    attempt: 1
})
Copy the code
  1. Change the image display mode to lazy by changing the SRC attribute of the img tag directly to V-lazy in the vue file:
<img v-lazy="/static/img/1.png">
Copy the code

Vue – LazyLoad github address for vue- LazyLoad

Route lazy loading

Vue is a single-page application, which may have a lot of routes introduced. In this way, the files packaged with WebPCAk are very large. When entering the home page, too many resources are loaded, and the page will appear white screen, which is not conducive to user experience. It would be much more efficient if we could split the components corresponding to different routes into different code blocks and then load the components only when the routes are accessed. This will greatly speed up the first screen, but may slow down the rest of the page.

Route lazy loading:

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})
Copy the code

The introduction of third-party plug-ins on demand

Import as needed according to the corresponding component library/plug-in documentation.

Optimize infinite list performance

If your application has very long or infinitely scrolling lists, you need to use windowing techniques to optimize performance, rendering only a few areas of content, reducing the time to re-render components and create DOM nodes. Refer to the following open source projects vue-virtual-Scroll list and vue-virtual-scroller to optimize this infinite list scenario.

Reference documentation

The front-end development specification: www.w3cschool.cn/webdevelopm…

RSCSS: RSCSS. IO/index. HTML

The front-end JavaScript specification document: xuanfengge.com/fedoc/index…

The front-end coding norms related to the performance optimization: xuanfengge.com/fedoc/code….

Vue Style Guide: cn.vuejs.org/v2/style-gu…

Bump laboratory: guide. Aotu. IO/docs/index….

Using VSCode + ESLint practice front-end coding standards: segmentfault.com/a/119000000…

Git Git: juejin.cn/post/684490…

Cz-cli:github.com/commitizen/…

Vue Project Performance Optimization – Practice Guide: juejin.cn/post/684490…

Using Eslint & standard specification front-end code: www.cnblogs.com/zhoumingjie…