The so-called no rules, no circumference, front-end time in the team code-review found that different developers at different times write a variety of code. So we came up with some code specifications that we hope will form the team’s code specifications in the future.

The purpose of the development specification

  • Unified coding style, specification, improve team collaboration efficiency
  • Output readable, maintainable, consistent code in a team environment

This article is published on gitthub: github.com/Michael-lzg…

HTML report

Enabling standard Mode

Use HTML5’s DocType to enable standard mode


      
Copy the code

Utf-8 encoding is used

<meta charset="utf-8" />
Copy the code

Preferentially use the latest version of IE and Chrome

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

Add a Viewport for a mobile device

<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no" />
Copy the code

Self-closing labels do not need to be closed

For example: img, input, br, hr, etc

<img src="https://xxx.png" alt="Google" />
<br />
<input type="text" name="title" />
Copy the code

Use semantic tags

HTML tags can be semantic. Use semantic tags instead of div or P tags

<! -- bad -->
<div>
  <p></p>
</div>

<! -- good -->
<header></header>
<footer></footer>
Copy the code

Attribute order requirements

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

id
class
name
data-xxx
src, for.type, href
title, alt
aria-xxx, role
Copy the code

CSS article

BEM naming principles

  • Block: modules with names and words connected by –
  • Element: element, a child element of a module, connected to a block by __
  • Modifier: modifier, a variant of a module that defines a special module to — connect to a block
/* For example */
.block__element{}.block--modifier{}Copy the code

Use CSS selectors effectively

Selectors should be nested at less than 3 levels

/* bad */
.page .header .login #username input{}/* good */
#username input{}Copy the code

Using CSS selectors effectively follows the following principles

  • Keep it simple and don’t use too many complex selectors.
  • Wildcards and attribute selectors are the least efficient and have the most elements to match, so avoid them.
  • Do not decorate element tags with class selectors and ID selectors.
  • Don’t sacrifice readability and maintainability for speed
  • Avoid CSS expressions

Choose expensive styles carefully

High cost attributes require a lot of computation by the browser before drawing:

Box-shadows Border-RADIUS Transparency Transforms CSS FiltersCopy the code

Avoid redrawing and rearranging

When a rearrangement occurs, the browser needs to recalculate the layout position and size, which is not good for performance optimization.

Common causes to redraw rearrange properties and methods

  • Add or remove visibleDOMElements;
  • Element size changes – margins, fills, borders, width, and height
  • Content changes, such as users ininputEnter text in the box
  • Browser window size changedresizeWhen the event occurs
  • To calculateoffsetWidthoffsetHeightattribute
  • Set up thestyleThe value of the attribute

Methods to reduce redrawing and rearrangement

  • usetransformalternativetop
  • usevisibilityreplacedisplay: noneBecause the former only causes redrawing, the latter causes backflow (changes the layout)
  • Do not put attribute values of nodes in a loop as variables in the loop.
  • Don’t usetableLayout, perhaps a small change can cause the entiretableRelayout of
  • Animation speed to achieve the choice, the faster the animation speed, the more reflux times, can also choose to userequestAnimationFrame
  • CSS selectors match from right to left to avoid too many layers of nodes

Javascript article

About the name

The common naming uses the small hump type naming

let userName = 'jack'
Copy the code

If I’m naming complex numbers, I need to add s, so let’s say I want to declare an array of people’s names

let names = new Array(a)Copy the code

Each constant should be named to make it easier for others to read the meaning

// good
const COL_NUM = 10
let row = Math.ceil(num / COL_NUM)

// bad
let row = Math.ceil(num / 10)
Copy the code

The naming should be semantic. If a function is named, it can be prefixed with a verb:

  • Can Determines whether an action can be performed
  • Has determines whether it contains a value
  • Is determines whether it is a value
  • Get Gets a value
  • Set Sets a value
// Whether it is readable
function canRead(){
   return true;
}
// Get the name
function getName{
   return this.name
}
Copy the code

About Strings

Use single quotes instead of double quotes

// bad
const name = 'jack'

// good
const name = 'jack'
Copy the code

Concatenate strings with string templates instead of ‘+’

function sayHi(name) {
  return 'How are you, ' + name + '? '
}

// good
function sayHi(name) {
  return `How are you, ${name}? `
}
Copy the code

About array

Assign values with literals

// bad
const items = new Array(a)// good
const items = []
Copy the code

Make a shallow copy of the array with the extension operator

// bad
let arr = [1.2.3]
const len = arr.length
const copyArr = []

for (let i = 0; i < len; i += 1) {
  copyArr[i] = arr[i]
}

// good
const copyArr = [...arr]
Copy the code

Use array. from to turn an array-like object into an Array.

const arrLike = { 0: 'foo'.1: 'bar'.2: 'baz'.length: 3 }

// bad
const arr = Array.prototype.slice.call(arrLike)

// good
const arr = Array.from(arrLike)
Copy the code

Using array deconstruction

const arr = [1.2.3.4]

// bad
const first = arr[0]
const second = arr[1]

// good
const [first, second] = arr
Copy the code

About the object

It is recommended to use literals for object and array creation because they are not only optimal for performance but also help save code.

// good
let obj = {
  name: 'Tom'.age: 15.sex: 'male',}// bad
let obj = {}
obj.name = 'Tom'
obj.age = 15
obj.sex = 'male'
Copy the code

ES6 uses attribute value abbreviations

const lukeSkywalker = 'Luke Skywalker'

// bad
const obj = {
  lukeSkywalker: lukeSkywalker,
}

// good
const obj = {
  lukeSkywalker,
}
Copy the code

Put the abbreviation for the property at the beginning of the object declaration

const anakinSkywalker = 'Anakin Skywalker'
const lukeSkywalker = 'Luke Skywalker'

// bad
const obj = {
  episodeOne: 1.twoJediWalkIntoACantina: 2,
  lukeSkywalker,
  episodeThree: 3.mayTheFourth: 4,
  anakinSkywalker,
}

// good
const obj = {
  lukeSkywalker,
  anakinSkywalker,
  episodeOne: 1.twoJediWalkIntoACantina: 2.episodeThree: 3.mayTheFourth: 4,}Copy the code

For shallow copies of objects, it is recommended to use the extended operator… , instead of object.assign. The rest operator is recommended when deconstructing an assignment to obtain several properties specified by an object. .

// very bad
const original = { a: 1.b: 2 }
const copy = Object.assign(original, { c: 3 })
delete copy.a // Change original

// bad
const original = { a: 1.b: 2 }
const copy = Object.assign({}, original, { c: 3 }) // copy => { a: 1, b: 2, c: 3 }

// good
const original = { a: 1.b: 2 }
constcopy = { ... original,c: 3 } // copy => { a: 1, b: 2, c: 3 }

const{ a, ... noA } = copy// noA => { b: 2, c: 3 }
Copy the code

About the function

Function arguments are assigned with default values instead of conditional statements.

// good
function createMicrobrewery(name = 'Jack') {... }// bad
function createMicrobrewery(name) {
  const userNameName = name || 'Jack'. }Copy the code

Use structure syntax for function arguments. The fewer the arguments, the better. If there are more than two arguments, use ES6’s destruct syntax, regardless of the order of the arguments.

// good
function createMenu({ title, body, buttonText, cancellable }) {... } createMenu({title: 'Foo'.body: 'Bar'.buttonText: 'Baz'.cancellable: true,})// bad
function createMenu(title, body, buttonText, cancellable) {
  // ...
}
Copy the code

Rest syntax is preferred… “Instead of arguments

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments)
  return args.join(' ')}// good
function concatenateAll(. args) {
  return args.join(' ')}Copy the code

Put the default parameter assignment last

// bad
function handleThings(opts = {}, name) {
  // ...
}

// good
function handleThings(name, opts = {}) {
  // ...
}
Copy the code

Use arrow functions whenever possible

// bad
[1.2.3].map(function (x) {
    const y = x + 1
    return x * y
  })

// good
 [1.2.3].map((x) = > {
    const y = x + 1
    return x * y
  })
Copy the code

About the module

Use (import/export) on nonstandard module systems

// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide')
module.exports = AirbnbStyleGuide.es6

// ok
import AirbnbStyleGuide from './AirbnbStyleGuide'
export default AirbnbStyleGuide.es6

// best
import { es6 } from './AirbnbStyleGuide'
export default es6
Copy the code

An entry is imported only once

// bad
import foo from 'foo'
/ /... Some other imports... //
import { named1, named2 } from 'foo'

// good
import foo, { named1, named2 } from 'foo'
Copy the code

In modules where there is only one export, use export Default

// bad
export function foo() {}

// good
export default function foo() {
Copy the code

The for loop

When you do a for loop, you take the length of the array, you take it in a variable, so it’s much more efficient for your code to execute, rather than having to recalculate the length of the array every time you go through the loop

// bad
for(var i = 0; i < arr.length; i++){

}

// good
for(var i = 0; len = arr.length; i < len; i++){

}
Copy the code

Vue article

Prop definitions are as detailed as possible.

The definition of a Prop should be as detailed as possible, at least specifying its type.

// bad
props: ['status']

// good
props: {
  status: String
}

// better
props: {
  status: {
    type: String.required: true.validator: function (value) {
      return ['syncing'.'synced'.'version-conflict'.'error'].indexOf(value) ! = =- 1}}}Copy the code

A key must be added for v-for traversal

In the traversal rendering of the list data, it is necessary to set a unique key value for each item, so that the internal mechanism of vue. js can accurately find the list data. When the state is updated, the new state value is compared to the old state value, locating diff more quickly.

<! -- bad -->
<ul>
  <li v-for="todo in todos">{{ todo.text }}</li>
</ul>

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

Don’t use v-if and V-for on the same element.

V-for has a higher priority than V-if. If you have to traverse the entire array every time, it will affect the speed, especially if you need to render a small portion.

<! -- bad -->
<ul>
  <li v-for="user in users" v-if="shouldShowUsers" :key="user.id">{{ user.name }}</li>
</ul>

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

The data of a component must be a function

Instances in JS are created by constructors. Each constructor can create multiple instances, so each instance inherits a method or property from the prototype. Vue’s data is actually a property on the Vue prototype that exists in memory.

When a component is reused multiple times, multiple instances are created. These instances use the same constructor if data is an object. Then all components share the same object. In order to ensure the data independence of components, each component must return an object as the state of the component through the data function, so that each time the component is reused, a new copy of data will be returned.

// bad
Vue.component('some-comp', {
  data: {
    foo: 'bar',}})// good
Vue.component('some-comp', {
  data: function () {
    return {
      foo: 'bar',}}})Copy the code

Component templates should be concise in writing

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

// bad
{{
  fullName.split(' ').map(function (word) {
    return word[0].toUpperCase() + word.slice(1)
  }).join(' ')}}// good
// In the template
{{ normalizedFullName }}
// The complex expression has been moved into a evaluated property
computed: {
  normalizedFullName: function () {
    return this.fullName.split(' ').map(function (word) {
      return word[0].toUpperCase() + word.slice(1)
    }).join(' ')}}Copy the code

Instructions for

<! -- bad -->
<input v-bind:value="newTodoText" :placeholder="newTodoInstructions" v-on:input="onInput" />
<! -- good -->
<input :value="newTodoText" :placeholder="newTodoInstructions" @input="onInput" />
Copy the code

Component names are multiple words

Our custom component names need to be multiple words during development to avoid conflicts with existing and future HTML elements, since all HTML element names are single words.

// good
Vue.component('todo-item', {
  // ...
})
export default {
  name: 'TodoItem'.// ...
}

// bad
Vue.component('todo', {
  // ...
})

export default {
  name: 'Todo'.// ...
}
Copy the code

Multiple properties to branch

In JavaScript, it is a common best practice to separate multiple properties of an object with multiple lines because it is easier to read.

<! -- good -->
<MyComponent 
    foo="a" 
    bar="b" 
    baz="c" 
/>

<! -- bad -->
<MyComponent foo="a" bar="b" baz="c" />
Copy the code

The order of element properties

Native attributes go first, instructions next, and pass parameters and methods last

  - class, id, ref
  - name, data-*, src, alt, for.type, href, value, max, min
  - title, placeholder, aria-*, role
  - required, readonly, disabled
  - v-model, v-for, key, v-if, v-show, v-bind,:
  - foo="a" bar="b" baz="c"
Copy the code

About styles within components

Set scope for the component style

/* bad  */
<style>
.btn-close {
  background-color: red;
}
</style>

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

To change the style of a third-party component library, you need to add a top-level scope.

/* bad */
.ivu-input {
  width: 254px ! important;
}

/* good */
.customerForm .ivu-input {
  width: 254px ! important;
}
/*.customerForm is the top-level DOM of the current component */
Copy the code

About Component Architecture

The component structure follows the template, script, and style structure from top to bottom.

<template>
  <div></div>
</template>

<script>
  export default {}
</script>

<style lang="scss" scoped></style>
Copy the code

The method members of the script section are placed in the following order.

- name
- components
- props
- data
- methods
- computed
- watch
- created
- mounted
- update
Copy the code

Clear the timer or event listener

Because some pages in the project will inevitably encounter the need for timers or event listening. However, when leaving the current page, if the timer is not properly cleared in a timely manner, it will cause confusion of business logic and even the application is stuck. In this case, it is necessary to clear the timer event listener, that is, in the page uninstall (close) life cycle function, clear the timer.

methods:{
  resizeFun () {
    this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
  },
  setTimer() {
    this.timer = setInterval((a)= > { })
  },
  clearTimer() {
		clearInterval(this.timer)
    this.timer = null
	}
},
mounted() {
  this.setTimer()
  window.addEventListener('resize'.this.resizeFun)
},
beforeDestroy() {
  window.removeEventListener('resize'.this.resizeFun)
  this.clearTimer()
}
Copy the code

The route was loaded lazily. Procedure

Vue is a single-page application, and many routes may be imported. In this way, the files packaged by WebPCAk are large. When entering the home page, too many resources are loaded, and the page will appear white screen, which is not good for user experience. It would be more efficient if we could split the components of different routes into separate code blocks and then load the components when the route is accessed.

{
  path: '/Home'.component: (a)= > import('@/views/Home.vue')}Copy the code

Responsibility of the single

Try to make each function do one thing at a time, rather than coupling all sorts of logic together, improving the reusability and readability of individual functions. For example, each page requests data when it is loaded and is presented to the page.

// bad
methods: {
  getList1() {
    // to do ...
  },
  getList2() {
    // to do ...
  }
},
created() {
  this.getList1()
  this.getList2()
},

// good
methods: {
  // Aggregate all requests in the init function
  init() {
    this.getList1()
    this.getList2()
  },
  getList1() {
    // to do ...
  },
  getList2() {
    // to do ...
  }
},
created() {
  this.init();
},
Copy the code

Third-party UI components are introduced on demand

The third party UI components we used in the project would be too large if we directly introduced the entire component library. We can use Babel-plugin-Component and then introduce only the required components to reduce the size of the project. The following is an example of introducing Vant to a project:

1. First, install babel-plugin-Component

npm install babel-plugin-component -D
Copy the code

2. Modify.babelrc

{
  "plugins": [["import", {
      "libraryName": "vant"."libraryDirectory": "es"."style": true}}]]Copy the code

3. Introduce some components:

import Vue from 'vue'
import { Button } from 'vant'

Vue.use(Button)
Copy the code

Photo paper:

Use the appropriate image format.

  • JPG: For content, images are mostly photos and so on.
  • PNG: Suitable for decorative images, usually more suitable for lossless compression.
  • GIF: Basically don’t use it except for GIF animations.
  • WebP: Greatly reduces the size of images, but has compatibility issues on mobile.

Use a Sprite chart

Sprites, CSS Sprites, also known as CSS Sprites, is a CSS image synthesis technology, mainly used for small picture display.

The advantage of Sprite graph is that many small images are combined into a large image, and the backround-position attribute value is used to determine the position of the image, which can reduce HTTP requests and achieve performance optimization.

Using iconfont

Iconfont (font icon), that is, through the font way to display ICONS, mostly used for rendering ICONS, simple graphics, special fonts, etc.

When using iconFont, because only the corresponding font file needs to be introduced, this method can effectively reduce the number of HTTP requests, and the general font size is small, so the request transmission data amount is less. Instead of importing images directly, iconFont allows you to set the size, color, and other styles just like a font, without distortion.

Lazy image loading

The SRC attribute of the image is not set, but the URL of the image is hidden, for example, first write in the data-src, and when some events trigger (such as scroll to the bottom, click load image), then the actual image URL into the SRC attribute. In order to achieve the image of the lazy loading.

function lazyload() {
  var images = document.getElementsByTagName('img')
  var len = images.length
  var n = 0 // Store the location where the image was loaded to avoid having to iterate from the first image every time
  return function () {
    var seeHeight = document.documentElement.clientHeight
    for (var i = n; i < len; i++) {
      if (images[i].getBoundingClientRect().top < seeHeight) {
        // Method 2: When the viewport top of the image appears in viewport
        if (images[i].getAttribute('src') = = ='images/default.jpg') {
          images[i].src = images[i].getAttribute('data-src')
        }
        n = n + 1}}}}Copy the code

The vue project can use the Vue-Lazyload plugin to load images lazily

Global import in main.js:

import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad, {
  preLoad: 1.error: require('./assets/img/error.jpg'),
  loading: require('./assets/img/homePage_top.jpg'),
  attempt: 2,})Copy the code

Page use

<li v-for="(item,index) in imgList">
  <img v-lazy="item" alt="" />
</li>
Copy the code

Recommend the article

Summary of 18 WebPack plugins, there’s always something you want!
Build a Vue-CLI4 + WebPack Mobile Framework (out of the box)
Build from zero to optimize a scaffolding similar to VUe-CLI
Encapsulate a TOAST and Dialog component and publish it to NPM
Build a WebPack project from scratch
Summarize a few ways to optimize WebPack packaging
Summarize the advanced application of VUE knowledge system
Summarize the practical skills of vUE knowledge system
Summarize the basic introduction of VUE knowledge system
Summary of mobile terminal H5 development commonly used skills (full of dry goods oh!)