From WeChat public number: niche Fang Qin The original link: https://mp.weixin.qq.com/s/gMCngLbxBOuTz5yevvWtpQ

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 the coding specification and Git specification of a team. It should be clearly understood that there is no silver bullet. The specification is to make the team unified, improve the code reading ability and reduce the code maintenance cost, etc. This paper records some common specifications in the code review of the project for reference only

JS part

Data in Vue is bidirectional data binding by default. If a large amount of data that is not related to rendering is placed directly in data, the performance consumed by bidirectional data binding will be wasted

The columns data in the table can be separately extracted from an external JS file as a configuration file. You can also define a constant in the current.vue file to define the columns data. Because the data is fixed and will not be modified anyway, it should be wrapped with Object.freeze. It can improve performance and remove fixed data. This operation is also recommended for fixed data in the front of some drop-down boxes

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

Note that object.freeze () can still be used to replace references to variables when the value is frozen. You can also use this syntax to ensure that the data does not change.

Control of the Modal box

A page usually has many bullet boxes with different functions. If each bullet box sets a corresponding variable to control its display, it will lead to the number of redundant variables and naming difficulties. You can use a variable to control the display of all Modal bullet boxes in the same page

For example, there are three Modal popboxes 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:    // modalType is modal1, modal2, modal3}}})Copy the code

Debounce use

For example, in remote search, data is dynamically obtained through an interface. If the interface requests each user input, bandwidth and performance are wasted

Multiple clicks of a button trigger multiple events. You can determine whether to execute the immediate command based on the scenario

<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} fromLodash Methods: {remoteMethod: debounce(function (query) {
        // to do ...
       // This is not a problem
    }, 200),}Copy the code

The picture

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

  • Picture compression problem, unless the special requirements of the picture must be high quality display, otherwise should be the corresponding compression processing
  • Selection of picture format for different business scenarios
    • JPG is good for rendering colorful images. JPG images often appear as large backgrounds, rotating images, or banners, etc
    • Logos, images or backgrounds with simple colors and strong contrast, need for transparency, etc
    • Combine commonly used small images with low variation frequency into Sprite images, which are more frequent and less than6KBThe picture ofbase64To deal with
    • According to the number of project pictures and user model distribution of the project, consider takingwebpImage processing

Route component parameters are transmitted

Using $route in a component makes it highly coupled to its corresponding route, limiting its flexibility by limiting its use to certain urls.

Decouple components and routes using props:

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: Route component parameter Transfer

Vue life cycle

In parent-child components, knowing the parent component’s lifecycle hook loading order allows the developer to do the right thing at the right time

1. The parent component

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

<script>
import List from  ./list

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>
Copy the code

2. The child component

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

<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>
Copy the code

3. Load sequence of parent and child components

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

4. Destruction sequence of parent and child components during destruction

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 life cycle, and then the parent component will do the corresponding processing

5. emit up

// The child component publishes the event in the corresponding hook
created(){
  this.$emit( done )
}

// The parent component subscribes to its message
<list @done="childDone">
Copy the code

6. hook

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

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

The Select optimized

Note That the options label must be on the same line during the drop-down list. If there is a line break, the selected value will be blank

// 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 dropdown 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

Data Data 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. Moreover, too deep level will lead to inconvenient data operation and processing, and the acquisition of data for fault tolerance processing is also cumbersome. Generally, it is best to keep 2-3 levels.

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

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

The processing is not convenient

// passed 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 hierarchy not only increases the maintainability and readability of code, but also the ease of operation and processing

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

You can operate on Person

// passed 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, to avoid excessive if else judgment, can also 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

Deconstruction assignment and default value. When the number of deconstruction is less than what, it is suitable to directly deconstruct and assign default value, whether the data should be aggregated

const { name = ' ', age = 10, gender = 'man' } = res.data

// bad
this.name = name
this.age = age
this.gender = gender

// good
this.person = {
  name,
  age,
  gender,
}
Copy the code

Responsibility of the single

Try to do one thing for a function at any time, rather than coupling all the logic together, improving the reusability and readability of individual functions

Each page requests data and presents it to the page when the load is complete

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

HTML part

HTML to write

Whether to write a template with too many attributes to wrap

<template> <! -- no line break --><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" /><! -- -- -- > a new line<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>
Copy the code

The CSS part

Style through

It is common to change third-party component styles during development, but due to the style isolation of the scoped property, you may need to remove scoped or create a different style. All of these have side effects (component style contamination, lack of elegance), and style penetration is only effective when used in CSS preprocessors.

  • 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 scoped ang="stylus">
  .content >>> .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 beautiful

After selector, property value

.custom-style {
  /* Space between the selector and {*/
  margin: 0; /* Before the attribute value */
  transform: scale(1.5.2.2); /* Add space */ after the comma
}
Copy the code

A newline

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

.custom-style {
  /* One or more attributes can be defined in a single declaration */
  background: background-clip background-color background-image
    background-origin background-position background-repeat background-size;
}
Copy the code

When a rule contains multiple selectors, each selector must be declared on a single line. If the rule is too long, horizontal scrolling is required to read the rest of the content. Try to make the reading order vertical

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

Nested hierarchy

Browsers parse CSS recursively from right to left. Too deep level nesting not only affects performance, but also reduces style reading and code maintenance. Generally, the layer shelf is controlled within 5 layers

Attribute order

Properties under the same rule should be grouped by function when written. And writing in order of Formatting Model > Box Model > Typographic > Visual to improve the readability of the code.

Explanation:

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

Also, for readability, if the content attribute is included, it should be placed first.

The original link