Specifications are relevant to every team and individual, because they affect not only the cost of maintaining and understanding code, but also the mood of development

There is no absolute optimal solution for a team’s code specification, Git specification, etc., and it should be clearly understood that there is no silver bullet. The specification is to unify the team, improve code reading, reduce code maintenance cost, etc. This article records some common specifications in project code review, for reference only

JS part

Data that is not relevant to rendering

The default value of vUE data is bi-directional data binding. The performance of bi-directional data binding is wasted if a large amount of data is placed in the data directly, which is not relevant to rendering. Remove the non-relevant data and use Object.Freeze to process it

You can also define a constant in the current.vue file to define the columns data. Since the columns data is fixed and will not be modified, you should use object.freeze to wrap the columns data. This can improve performance and remove fixed data. This is also recommended for some data fixed in the front of the drop down box

const columnList = Object.freeze([
  { title: 'name'.key: 'name'.align: 'center' },
  { title: 'gender'.key: 'gender'.align: 'center' }
])
Copy the code

Note that object.freeze () freezes values, so you can still replace references to variables, and ensure that the data doesn’t change. If you want to modify and interact with the data, you don’t want to freeze it.

ModalThe control of the frame

A page usually has many different functions of the pop-up, if each pop-up set a corresponding variable to control its display, it will lead to the number of variables more redundant and naming difficulties, you can use a variable to control the display of all Modal pop-up in the same page

Let’s say you have three Modal boxes on a page

// bad
// Each data control corresponds to Modal display and hide
new Vue({
    data() {
        return {
 modal1: false. modal2: false. modal3: false. }  } })  // good // Display the corresponding pop-up box when modalType is the corresponding value new Vue({  data() {  return {  modalType: ' ' // The modalType value is modal1, modal2, and modal3  }  } }) Copy the code

debounceuse

For example, data needs to be obtained dynamically through the interface during remote search. If the interface requests each user’s input, bandwidth and performance will be wasted

When a button is clicked multiple times, events are triggered multiple times, depending on whether the scenario is executed immediately or not

<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
Copy the code
import {debounce} from 'lodash'

Methods: {The remoteMethod: debounce (function (query) {
        // to do ...
 // There is no problem with this  }, 200), } Copy the code

The picture

In the process of function development, image processing is often relatively easy to be ignored, and will affect the efficiency of development and page performance to a certain extent

  • Image compression, unless the special requirements of the image must be high quality display, otherwise should be the corresponding compression processing

  • Image format selection for different business scenarios

    • JPG is great for rendering colorful images. JPG images often appear as large backgrounds, rosters, banners, etc
    • Logo, pictures or backgrounds with simple colors and strong contrast, need transparency, etc
    • The commonly used and the change frequency is very low small images are combined into Sprite chart, for the change is more frequent and less than6KBPicture ofbase64To deal with
    • According to the number of project pictures and the distribution of user models, etcwebpThe processing of the picture

Routing components pass parameters

Using a $route in a component makes it highly coupled to its corresponding route, limiting its flexibility by making the component usable only at certain urls.

Use props to decouple components from routes:

Replace with$routeThe coupling of

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
  routes: [
 { path: '/user/:id'.component: User }  ] }) Copy the code

throughpropsThe decoupling

This allows you to use the component anywhere, making it easier to reuse and test.

const User = {
  props: ['id'].  template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
 routes: [  { path: '/user/:id'.component: User, props: true },   // For routes that contain named views, you must add the props option for each named view:  {  path: '/user/:id'. components: { default: User, sidebar: Sidebar },  props: { default: true.sidebar: false }  }  ] }) Copy the code

Reference: Routing component pass parameters

Vue Life cycle

In the case of parent and child components, understanding the hook load sequence of parent and child components allows developers to do the right thing at the right time. This question has been asked at least three times in recent interviews

<template>
  <div>
    <h3>home</h3>
    <list @hook:mounted="listMounted" />
  </div>
</template>

<script> import List from './list'

Copy the code

export default { name: "home", components: { List }, methods: { listMounted(){ console.log('------------ listMounted'); } }, beforeCreate() { console.log("home beforeCreate"); }, created() { console.log("home created"); }, beforeMount() { console.log("home beforeMount"); }, mounted() { console.log("home mounted"); }, beforeDestroy() { console.log("home beforeDestroy"); }, destroyed() { console.log("home destroyed"); } } </script>

Child components

<template>
  <div>
    list
  </div>
</template>
Copy the code

<script> export default { naem: "list", beforeCreate() { console.log("list beforeCreate"); }, created() { console.log("list created"); }, beforeMount() { console.log("list beforeMount"); }, mounted() { console.log("list mounted"); }, beforeDestroy() { console.log("list beforeDestroy"); }, destroyed() { console.log("list destroyed"); } } </script>

Load order of parent and child components at load time

home beforeCreate --> home created --> home beforeMount --> list created --> list beforeMount --> list mounted
Copy the code

The sequence in which the parent and child components are destroyed

home beforeDestroy --> list beforeDestroy --> list destroyed --> home destroyed
Copy the code

In the actual development process, the parent component will be notified when the child component completes a certain lifecycle, and then the parent component will do the corresponding processing

emit up

$emit(){this.emit ('done')}Copy the code

< list@done ="childDone"> < list@done ="childDone">

hook

Listen for the life cycle of the child component via @hook

<list @hook:mounted="listMounted" />
Copy the code

SelectTo optimize the

Note that the options TAB stays on the same line as the drop-down box. If there is a newline, the selected value will have extra white space

<! -- bad -->
<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">
        {{item.label}}
    </Option>
</Select> Copy the code

You need to keep the Options and drop – down values on the same line

<! -- good -->
<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
Copy the code

dataData hierarchy

Data data with hierarchical structure, do not too flat or nested hierarchy too deep, if excessive flat namespace conflicts can lead to data, parameters and process, if it is a nested hierarchy too deep will lead to the vue data hijacking recursion level too deep, if nested hierarchy of ecstasy that, careful recursive stack problem. And too deep level will lead to data operation and processing inconvenience, obtaining data to do fault tolerance processing is also cumbersome. Generally, two or three layers are best.

If there is only one layer of data, it is too flat

{
    name: '',
    age: '',
    gender: ''
}
Copy the code

This results in inconvenient processing

// Pass it as an interface parameter
ajax({
 this.name, this.age, this.gender
})

// Interface to obtain data, batch processing ajax().then(res= > {  const {name, age, gender} = res.data  this.name = name  this.age = age  this.gender = gender }) Copy the code

Proper hierarchies not only increase code maintenance and readability, but also ease of manipulation and processing

{
    person: { // Personal information
        name: ' '.        age: ' '.        gender: ' '
 } } Copy the code

You can operate against the Person

// Pass it as an interface parameter
ajax(this.person)

// Interface to obtain data, batch processing
ajax().then(res= > {
 const {name, age, gender} = res.data  this. $set(this, 'person', {name, age, gender}) }) Copy the code

The strategy pattern

The use of policy mode avoids excessive if else judgment and can replace simple logic switch

const formatDemandItemType = (value) = > {
    switch (value) {
        case 1:
            return 'base'
        case 2:
 return 'senior'  case 3:  return 'VIP'  } }  // Policy mode const formatDemandItemType2 = (value) = > {  const obj = {  1: 'base'. 2: 'senior'. 3: 'VIP'. }   return obj[value] } Copy the code

deconstruction

Destruct assignment and default value, when the number of destruct is less than what is suitable for direct destruct and assign default value, whether the data is related to aggregation processing

const {
  naem = ' '.  age = 10.  gender = 'man'
} = res.data
 // bad this.name = name this.age = age this.gender = gender  // good this.person = {  naem,  age,  gender } 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

Each page requests data when it is loaded and is presented to the page

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

v-bind

In the daily development process, the extraction and encapsulation of components is a very routine operation, but when the component needs a lot of parameters, it will lead to the passing of a bunch of prop, not only the writing is tedious, the maintenance and reading of the code is not a good thing

For example, the test-demo component needs props

When using

<template> <test-demo :data1="data1" :data2="data2" :data3="data3" ... Suppose there's a bunch of /> </template>Copy the code

The test-demo needs to be processed

{ props: ['data1', 'data2', 'data3', ...] } // or props: {modalVisible: {type: String, default: false}, data1: {type: String, default: '1' }, data2: { type: String, default: '2' }, data3: { type: String, default: '3' } }Copy the code
  • advice

Collect the data required by the child component, put it in an object, and pass the object using v-bind. The child component uses the common props

<template>
	<test-demo 
    v-bind="obj"
  />
</ template>
Copy the code

<script> export default {data () {return {obj: {// collect data1: '1', data2: '2', data3: '3' } } } } </script>

HTML part

htmlwriting

If there are too many properties when writing a template, whether to wrap lines

<template> <! <VueButton class="icon-button go-up" icon-left="keyboard_arrow_up" v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')" @click="openParentFolder" />Copy the code

<! <VueButton class="icon-button go-up" icon-left="keyboard_arrow_up" v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')" @click="openParentFolder" /> </template>

The entity using

HTML displays characters such as <, >,&, etc., using character entities instead

<! -- bad -->
<div>
  > 1 & < 12
</div>
  
<! -- bad --> <div>  &gt; 1 &amp; &lt; 12 </div> Copy the code

The CSS part

Style through

It is common to change the style of third-party components during development, but due to the style isolation of the scoped property, you may need to remove scoped or start a new style. All of these practices have side effects (component style contamination, lack of elegance), and style penetration only takes effect when used in the CSS preprocessor.

  • Use/deep/less

<style scoped lang="less">
.content /deep/ .el-button {
	 height: 60px;
}
</style>
Copy the code
  • SCSS use: : v – deep

<style scoped lang="scss">
.content ::v-deep .el-button {
  height: 60px;
}
</style>
Copy the code

  • Stylus used > > >
<style style ="stylus"> >. Custon-components {height: 60px; } </style>Copy the code

The blank space

Proper whitespace improves the reading experience of your code, making it more elegant and aesthetically pleasing

After the selector, property value

.custom-style {// margin: 0; Transform: scale(1.5, 2.2); // Add a space after the comma}Copy the code

A newline

And HTML types. When a line has many attributes, appropriate line wrapping can improve reading and aesthetics

.custom-style{// you can define one or more properties in a declaration. Background: background-clip background-color background-image background-origin background-position background-repeat background-size; }Copy the code

When a rule contains more than one selector, each selector declaration must have its own line, which is too long to scroll horizontally to read the rest of the content. You should try to keep the reading order vertical

.custom.header. title,.other.header. title {color: #f0f; }Copy the code

Nested hierarchy

Browsers are recursively matched from right to left when parsing CSS. Too deep hierarchical nesting not only affects performance, but also reduces style reading and code maintainability. Generally, the hierarchy is limited to five layers

Double quotation marks

Attribute selector values must be enclosed in double quotes. Single and non-quotes are not allowed. Double quotes are recommended for HTML attribute values, and single quotes are recommended for JS attribute values

.custom-style{
	font-family: "PingFang SC", "STHeitiSC-Light";  
}
Copy the code

Attribute order

Attributes under the same rule should be grouped by function when written. Formatting Model > Box Model > Typographic > Visual to improve code readability.

Explanation:

  • Formatting Model Related attributes include position, top, right, bottom, left, float, display, and overflow
  • Box Model related properties include: border/margin/padding/width/height and so on
  • Typographic properties include font/line-height/text-align/word-wrap
  • Visual related properties include background/color/transition/list-style, etc

Also, for readability, if you include the content attribute, put it first.

reference

  • A summary of three years of Vue front-end development in Blood and tears
  • Code specification function