Tips: This specification is required by the company, I hope you can help to make more suggestions ~

About business code data specifications

In this specification, words are named in the hump form

Buttons with business functions

For buttons with certain service functions, such as adding a user, deleting a user, editing a user, etc., we name them with handle beginning and service ending. Take the following cases as an example:

Button business named
Add user handleUserAdd
Delete user handleUserDel
Edit the user handleUserEdit
Deleting Users in Batches handleUserDelBatch
Import user Excel importUserExcel
Exporting user Excel exportUserExcel

If the name of our method is the same as the name of the interface we imported, we should change the name of the imported interface as the first action

**

Normal naming method

Just name it something that makes sense

Search criteria and table data naming

This will be divided into two cases, the first case is not the same name, and the other case is the same name

There are no duplicate names

Field meaning named
The search criteria searchApi
Tabular data tableData
The tree of data treeData

There are duplicate names

We can name each condition according to the actual business. Examples are given below:

Field meaning named
Search city list criteria citySearchApi
City table data cityTableData
Tree data for cities cityTreeData

For data specifications in data

There are two cases

Not much data

As follows

		{
      stringVariable: "",
  		nullVariable|numberVariable:null,	
  		arrayVariable:[],
			objectVariable:{},
			arrayObjectVariable:[{},{}]
    }
Copy the code

Groups by service

		{
  		//group1
      stringVariable: "",
  		nullVariable|numberVariable:null.arrayVariable: [].objectVariable: {},arrayObjectVariable: [{}, {}]//group2
      stringVariable: "",
  		nullVariable|numberVariable:null.arrayVariable: [].objectVariable: {},arrayObjectVariable: / {}, {}}Copy the code

Specification for writing method annotations

You need to provide a method with its variables and annotations for its actions

/ * * *@description: Function of method *@param {parameter type} Parameter name // If received parameter *@param {parameter type} Parameter Name *@return {return value type}	// If there is a return value */
Copy the code

Interface API writing specification


/ * * *@func Interface name *@param  Params // Params is a request parameter placed in the request header. Optional *@param  Data // Data is an argument placed in the request body ~ optional *@description Interface description */
export const getAuthUserList = (params,data) = > {
  return request({
    url: '/auth/role/list'.// The interface requested url
    method: 'get'.// Interface request mode
    params,	/ / request header parameter
    data	// Request Boyd parameter})}Copy the code

Tips: For interface requests that belong to the same functional module, we should put them in the same JS file and wrap them in the form shown above

**

API usage specifications

import { getAuthUserList } from '@/api/auth'

/ /... The omitted part.....

async getuserList(){

  try{
  	const res = await getAuthUserList()
    / /...
  }catch{
  	// do something}}Copy the code

Specification for use of Vuex

State, which is often called in the page, needs to be exposed in the getter

Code specification

Key about v-for

It is always not recommended to use index directly as the key for the current list, and other unique values should be used as keys whenever possible

With regard to V-IF and V-show, it is important to clarify the difference between the two

If v-if is false, it will not initially render, and if v-if is toggled, it will always re-render

V-show will render regardless of the initial value, and the toggle value is simply toggle display: None. This CSS is more recommended for scenarios where the display is toggled too frequently, and there is no forced update of the content view

About the v – once

For some things that only need to be rendered once, v-once is more recommended

If v-once is used in v-for, we must add a key to this element


About view force rendering

One of the following two approaches is always recommended

forceUpdate  


//component.vue
export default {
  methods: {componentUpdate(){
      this.$forceUpdate()
    }
  }
}
Copy the code

key 

//component.vue
<template>
  <component-child :key='componentChildKey'></component-child>
</template>
<script>
  export default {
    data(){
      return {
        componentChildKey:1
      }
    },
    methods:{
      upDateComponentChild(){
        this.componentChildKey += 1
      }
    }
  }
</script>
Copy the code

About the processing of data

Filter out fields we don’t need

For some business scenarios, if there is some data returned from the back end that we do not need, we should use a map map to simply process the data when we receive it

/ /...
try{
	const res = await getDates()
  this.tableData = res.map(el= > {
  	let {a,b,c} = el
    return{a,b,c}
  }}
}catrh{return}

/ /...
Copy the code

Process data that does not require responsive change

Freeze ()** Disables the implementation of vue, which disables the implementation of any additional information without the configured property of false. The vue works without any additional information, and provides a different information system, which disables any additional information. Something like Object. PreventExtensions

A value in an array or object that determines whether a condition exists

For an array of

To find values directly, we can use array. includes, array. indexOf, etc. For conditional values, we can use array. some

For the object

If we have a similar need to see if there are fields that match certain criteria, we can start by using Object.entries to line up their own enumerable properties and pull down the array

On the Promise

For asynchronous requests, I always recommend writing them in a try catch, which is already used in an example above

For complex if condition judgment

If there are two or more criteria in an if (), or if the criteria are used more than once in the code block, we should use a properly named variable to store the result

About Watch computed Methods

First, let’s clarify their usage scenarios:

  1. watch

Listen for one piece of data, it affects multiple pieces of data or when it changes, we need to do a lot of other things

  1. computed

It is dependent on other data for change, or the calculation of this data has a significant performance cost

  1. methods

It’s updated in real time

Service scenario: Listen to multiple data at the same time

<script>
export default(){
  computed:{
    handleChange(){
      const {fileName,FolderName} = this.$props
    }
  },
    watch:{
      handleChange:{
        handler:function(val,oldval){
          //do somting
        },
        immediate:true
      }
    }
}
</script>
Copy the code

Css writing specifications

Nomenclature semantics

Don’t use appearances and obscure names. Here are some examples of mistakes

<div class='red'></div>
Copy the code

Tips: Do not use ids unless necessary

Order problem

When we write CSS properties, we should follow the following order as much as possible

1. Position properties (position, display, float, z-index, etc.) 2. Width, height, padding, margin) 3. Text related 4. Background related (background, border, etc.) 5. Others (animation, transition, etc.)

Reflux and redraw problems

If a piece of CSS is likely to change frequently, then we need to consider the performance cost of backflow and redraw. We use transition and transform instead of transiton and transform, as shown below:

transform
value describe
none Definition does not transform.
matrix(n.n.n.n.n.n) Define a 2D transformation using a matrix of six values.
matrix3d(n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n) Define a 3D transformation using a 4×4 matrix of 16 values.
translate(x.y) Define 2D transformations.
translate3d(x.y.z) Define 3D transformations.
translateX(x) Define the transformation, just using the X-axis values.
translateY(y) Define the transformation, just using the Y-axis value.
translateZ(z) Define the 3D transformation using only the z-axis values.
scale(x.y) Define 2D scale transformations.
scale3d(x.y.z) Define the 3D zoom transformation.
scaleX(x) Define the scale transformation by setting the value of the X axis.
scaleY(y) Define the scale transformation by setting the Y-axis value.
scaleZ(z) Define the 3D scale transformation by setting the z-axis value.
rotate(angle) Define 2D rotation, specifying angles in parameters.
rotate3d(x.y.z.angle) Define 3D rotation.
rotateX(angle) Defines a 3D rotation along the X axis.
rotateY(angle) Define 3D rotation along the Y-axis.
rotateZ(angle) Define 3D rotation along the Z axis.
skew(x-angle.y-angle) Defines 2D skew conversions along the X and Y axes.
skewX(angle) Defines a 2D tilt transformation along the X axis.
skewY(angle) Define a 2D tilt transformation along the Y-axis.
perspective(n) Define perspective views for 3D transformation elements.
Default value: none
Inheritance: no
Version: CSS3
JavaScript syntax: object.style.transform=”rotate(7deg)”


transtion
value describe
transtion-property Specifies the name of the CSS property that sets the transition effect.
transtion-duration Specifies how many seconds or milliseconds it takes to complete the transition effect.
transtion-timing-function The speed curve specifying the speed effect.
transtion-delay Define when transition effects begin.
Default value: all 0 ease 0
Inheritance: no
Version: CSS3
JavaScript syntax: object.style.transition=”width 2s”

Try to avoid using label names

Try to avoid writing:

.app-header span{
	
}
Copy the code

The following is recommended

.app-header>.name-title{

}
Copy the code

Css comment specification

/* * block comment */ /* single line comment text */Copy the code


About general framework use

routing

Lazy loading

First, for routing, we use lazy loading

{
   path: '/home',
   name: 'home',
   component: import(/* webpackChunkName: 'Chunk name you want to set' */'.. /page/home') }Copy the code

permissions

Our internal routing system has two parts, one is static routing, one is dynamic routing and if we need to access dynamic routing after the permission is introduced, Can open the SRC/store/modules/permission. Js to generateRoutes below the action, switch comment area

component

Separate page

I have already set a class for our outermost layer. If it is not necessary, please do not set a separate class to control it. The details are in app.vue ~

Lazy loading

It is important to note that for components like Modal, we should always use lazy loading. Here /* webpackChunkName: “[request]” */ in request represents the actual parsed file name.

const PageFooter = () = > import(/* webpackChunkName: "[request]" */'_c/PageFooter')

export default {
    components: {
        'page-footer':pageFooter
    }
}
Copy the code

permissions

Some of the button permissions within our component will be placed in the meta

The case where you only need to control a single button:
<template> <div> < el-button V-permission :delete="roles"> Button </ el-button > </div> </template> <script> computed: { hasSelected() { return this.delUserList.length > 0 }, roles() { return this.$route.meta.roles ? this.$route.meta.roles : [] } }, </script>Copy the code

Controls the condition of conditional rendering
<template> <div> <div V-if ='hasRole'> conditional render area </div> </div> </template> <script> computed: { hasRole() { const arr = ['add', 'edit', 'delete'] const hasRole = arr.some(el => { return this.roles.some(e => e === el) }) return hasRole } roles() { return this.$route.meta.roles ? this.$route.meta.roles : [] } }, </script>Copy the code


SearchForm

This is a form search component that only provides some simple functions at present. It is suggested that only type can be used at present: El-input, el-select, el-date-picker, until I write the partial document, there can be only one ~ method in the same SearchForm, and only one ~ method can be used.

<template>
  <div class="card-block">
    <search-form :list="formList" :search-width="200" @change="initChange" />
  </div>
</template>

<script>
const SearchForm = () => import('_c/SearchForm')
export default {
  components: {
    'search-form': SearchForm
  },
  data() {
    return {
      formList: [
        {
          name: 'name',
          type: 'el-input',
          value: '',
          placeholder: '请输入姓名'
        },
        {
          name: 'age',
          type: 'el-select',
          value: '',
          placeholder: '请输入岁数',
          children: {
            type: 'el-option',
            list: [{
              value: '选项1',
              label: '黄金糕',
              title: '黄金糕'
            },
            {
              value: '选项2',
              label: '黄金糕2',
              title: '黄金糕2'
            }]
          }
        },
        {
          name: 'time',
          type: 'el-date-picker',
          //指定单个表单的宽度,如果不写,则会取上面的search-width,如果search-width也没有给,则是会取默认宽度180
          width: 450	
        }
      ],
      pageApi: {
        Index: 1,
        PageSize: 10
      }
    }
  },
  methods: {
    initChange(date) {
      // 全并查询条件
      this.pageApi = Object.assign(this.pageApi, date)
      console.log(this.pageApi)
    }
  }
}
</script>

Copy the code