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.
Modal
The 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
debounce
use
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 than
6KB
Picture ofbase64
To deal with - According to the number of project pictures and the distribution of user models, etc
webp
The 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$route
The coupling of
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id'.component: User } ] }) Copy the code
throughprops
The 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
Select
To 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
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. 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
html
writing
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> > 1 & < 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