After the study of the project structure/development mode/technical architecture, some points that can be optimized are proposed again.

After I just joined the new company and learned the development technology of the new company, I couldn’t wait to integrate my past development methods and skills into the current project. The following are the improvement ideas for some technical points of the current project

This scheme mainly consists of the following points:

  1. Code writing specification
  2. The Api layer
  3. Request tool more efficient encapsulation
  4. Route separation configuration scheme
  5. Directory structure arrangement
  6. Data request optimization
  7. Mock data configuration

The program is in the process of continuous compilation, other contents need to be discovered and sorted out together.


Code writing specification

Good code writing specifications can greatly improve the efficiency of project development, increase the readability/maintainability/testability of code, and reduce the complexity of development/refactoring scenarios.

Code specifications can be divided into construction specifications/writing specifications and other aspects, such as construction of project structure, maintenance of explanatory documents, construction and naming of modules, comments in the code and writing of business code and other aspects should be taken into account and set up unified/better rules to restrict, the following is a simple explanation:

Project structure reconstruction

During the construction of the project structure, the Directory Structure Specification Document should be maintained continuously, and the project structure version, such as 1.0.0, should be annotated as follows:

  1. Action description of the new and change process in the structure
  2. Project structure version information

Directory and module file naming

According to the project currently under development, some rules are sorted out as follows:

  1. The general directory name is lowercase, and the directory consists of multiple word components connected by “-“, such as:

    router,

    store,

    components,

    store/modules,

    utils/dygraph-plugin

  2. The middle route view directory is named with a big hump, for example:

    views/Algorithms

    views/Events

    views/Monitor

  3. The tool module, the basic business module file is lowercase, and the directory from multiple word components is connected with “-“, such as:

    Bin /babel-external-helpers.js

    store/modules/event.js

  4. Components are named in a big hump, for example:

    AlgorithmsCenter.vue

    AlgorithmsDdetail.vue

Refer to the vue.js style guide for specific naming methods.

Code writing specification

The code should be written in accordance with the basic development specification guidelines, which are only recommended here.

Name method of the block-element-modifier (BEM) structure

HTML DOM structure and standard as far as possible to comply with the BEM naming method, for details, please refer to: BEM- front-end naming specification introduction, BEM- derived from Yandex CSS naming methodology.

Note: it is not necessary to use it everywhere, but when a node does not belong to any OF the BEM categories, it can be named as usual.

Object Oriented CSS (OOCSS) compilation method

OOCSS is not new (CSS) object-oriented technology, it will want to show is that we can actually style with fixed dom decoupling, add one or more small CSS styles to need the dom node, the purpose was to increase the rate of code reuse, and code readability will have the very big enhancement, In the project especially recommended to use BEM + OOCSS development mode, there are a lot of combined use guide online, here to provide you with a very simple CSS component scheme: OOCSS + BEM.

The Javascript specification can refer to Eslint for more detailed rules. The Google Javascript specification is also a good choice, such as:

Reject var 2. Use Spaces instead of tabs 3. Use arrow functions in preference 4. Use the template string instead of the connection string 5....Copy the code

Here are Kissy best coding practices from Ali.

Annotation way

More attention should be paid to comments. Good comments can greatly improve the readability of your code.

HTML documents should comment the beginning and end of each Block on the page, as well as individual elements, for example:

<div class="events-center"> <! The header diagram shows start --> <div class="top-chart">
  	<stacked-bar-chart :counts="eventCounts" :color="eventColor" @click="handleBarClick"></stacked-bar-chart> </div> <! -- Header diagram shows end --> <! -- Search and manipulation module start --> <div class="toolbar horizontal background"> <! -- Search function component --> <cv-search :placeholder="helloWord" v-model="query"></cv-search> <! Set button --> <div v-if=! "" filterToggle" @click="openFilter" class="filter-icon"><icon-settings /></div> <! --> <div v-if=! "" filterToggle" @click="switchMode" class="filter-icon"><icon-mode /></div> <! Start --> <cv-button v-if="filterToggle" kind="secondary" @click="resetFilter"</cv-button> <cv-button v-if="filterToggle" kind="secondary" @click="cancelFilter"</cv-button> <cv-button v-if="filterToggle" @click="confirmFilter"</cv-button> <! </div> <! End --> </div>Copy the code

CSS should also be annotated according to the structure of the code written, using multi-line comments as much as possible (/**/), as follows:


/* css reset start*/
*{
  box-sizing: border-box
}
body {
  margin: 0;
  background-color: #FFF;
  font-family: MicrosoftYaHei, PingFangSC, Helvetica, Arial, sans-serif, "宋体"; } / /... /* elemnt-ui table */. El-table tr {background-color: elemnt-ui;#f3f3f3;
  cursor: pointer;
}
// ...
Copy the code

JS annotations hope to adopt the way recommended by JSDoc, which is more conducive to a certain stage of development, using JSDoc tool to directly generate documents about the JS module, specific documents can refer to: JSDoc online documents, JSDoc Chinese documents

* @module utils/ JSDoc * @see module:main.js */ /** Expose name */export const name = 'mixer'; * @param {object} error - Error object. * @param {string} errorMessage - Error alert message. * @return* @example * errorTip(this, e,'Login failed') * /export functionErrorTip (self, error, errorMessage) {// Error text message after processinglet message = translate(error.message || error.msg || 'Error, please try again'Console. log(error, message) // Calls the vue instance's message prompt method self.$message({
    type: 'error',
    message: errorMessage || message,
    center: true,
    duration: (error.message && error.message.indexOf('Network Error')! = = 1)? 8000:3000})return@param {string} message - An error message in the original error objectreturn{string} Error message after processing. */function translate (message) {
  if (message.indexOf('timeout') !== -1) {
    return 'Request timed out'
  } else if (message.indexOf('Network Error') !== -1) {
    return 'Network error'
  } else {
    return 'Error, please try again'}}Copy the code

How to generate the document:

  1. Download jsdoc-to-MarkDown to output the document as markdown

    npm install --save-dev jsdoc-to-markdown
    Copy the code
  2. The configuration scripts

    {
      "scripts": {
        "docs": "jsdoc2md lib/*.js > api.md"}}Copy the code
  3. Perform a task

    npm run docs
    Copy the code

All js files in lib can be generated into api.md according to the Jsdoc specification.


Efficient encapsulation of the Request tool

More efficient encapsulation for AXIos, such as interceptors that can fail a data request based on the status of the result when it comes back, and so on.

config/axios.config.js:

/** * axios config * @module config/axios.config * @see utils/request */ import qs from'qs'; /** * const axiosConfig = {baseURL: {baseURL: {baseURL: {baseURL: {baseURL: {baseURL: Process.env.restapi_prefix, // Pre-request data processing transformRequest: [function (data) {
        returndata; }], // After the request data processing: [function (data) {
        returndata; }], // headers: {'X-Requested-With': 'XMLHttpRequest'.'Content-Type': 'application/x-www-form-urlencoded'}, // Query the object serializer function paramsSerializer:function (params) {
        returnqs.stringify(params); }, // Set timeout to s timeout: 10000, // With the credentials:true// Customize request processing // adapter:function(resolve, reject, config) {}, json/blob /document/arrayBuffer/text/stream responseType:'json', // XSRF set xsrfCookieName:'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN'// Upload and download progress callback onUploadProgress:function (progressEvent) {
        Math.round(progressEvent.loaded * 100 / progressEvent.total);
    },
    onDownloadProgress: function(progressEvent) { Math.round(progressEvent.loaded * 100 / progressEvent.total); }, // maximum forwarding numbers for node.js maxRedirects: 5, // Maximum response data size maxContentLength: 2000, // Define error status code range validateStatus:function (status) {
        returnstatus >= 200 && status < 300; }, // for node.js // httpAgent: new http.agent ({keepAlive:true }),
    // httpsAgent: new https.Agent({ keepAlive: true})}; /** Export configuration module */export default axiosConfig;

Copy the code

Utils /request.js(currently restapi.js): utils/request.js

/** * ajax request tool module * @module utils/request * @see main.js */ import axios from'axios';
import config from '.. /config/axios.config';
import qs from 'querystring'
import Vue from 'vue'
import { errorTip } from 'utils/common'Const vueInstance = new vue () // Constructed request object const request = axios.create(config); / / return status determine response interceptor (add) request. Interceptors. Response. Use (res = > {/ / if data request failedif ( res.data.code  > 300 ) {
          errorTip(vueInstance, res.data)
          return Promise.reject(res.data);
        }
        return res.data.data;
    },
    error => {
        returnPromise.reject(error); }); request.interceptors.request.use((config) => {let allowMethods = ['post'];
    if(allowMethods.indexOf(config.method) ! == -1) { config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
        config.data = qs.stringify(config.data);
    }
    return config;
}, (error) => {
    returnPromise.reject(error); }); // Repackage the instance of Axios as a plugin for vue.use (XXXX)export default request;

Copy the code

Api out of

Set up an API directory structure in the SRC development directory, where you can build modules for all requested actions centrally for invocation.

api/index.js:

/** * API interface call maintenance module * @module API * @see main */ import request from'utils/request'
  import Vue from 'vue'
  import { errorTip } from 'utils/common'Const vueInstance = new vue () /** * Paging algorithm list * @param {Object} [p] pageInfo Page information * @param {number} [p.page] Number of pages * @param {number} [p.size] size Number of data on a page * @param {string} [p.labels] Labels * @param {string} [p.query] query Query condition * @return{Promise} request Request action Promise */export let apiGetList = ({page = 1, size = 10, labels = 'anomaly', query = ' '} = {}) => {
    returnrequest.get(`/algorithm? page=${page}&labels=${labels}&size=${size}&query=${query}`).catch(error => errorTip(vueInstance, error))
  }
Copy the code

Data request action optimization

Optimize the processing of the request with async await and avoid nesting of callback functions with async/await where the request needs to be called.

store/modules/setting.js:

import { apiGetList } from 'api'/ /... GetList: ({commit}, {page = 1, size = 10, labels ='anomaly', query = ' '} = {}) => {
      return new Promise((resolve, reject) => {
        restapi.request({
          method: 'get', url: `/algorithm? page=${page}&labels=${labels}&size=${size}&query=${query}`,
          success: sdata => {
            commit('LIST_ALGORITHMS'Resolve (sdata)}, error: reject})})}, getListTest: async ({commit}, params) => {let sdata = await apiGetList(params)
      commit('LIST_ALGORITHMS', sdata)
    }
    // ...
}
Copy the code

There is basically no difference in how the views are called, and no request error handling is required.

views/Algorithms/AlgorithmsCenter.vue

methods: { ... mapActions('algorithm'['getList'.'getListTest'.'getCount']), / /... getAlgorithmsList ({start = 1, length = 10} = {}) { // this.getList({page: Math.ceil(start / length), size: Length, labels: this.algoType}). Catch (error => errorTip(this, error)) Math.ceil(start/length), size: length, labels: this.algoType}) }Copy the code

Mock data scaffolding

Mock data construction is conducive to simulating data requests when the development progress of the front and back ends is not synchronized, so that the front-end interaction logic can be completed according to the request. With reasonable configuration, the real interface on the line can be called with slight changes after the real interface is available, and the processing method is smoother.

Mock structures, there are many ways, here it is recommended to use json – the use of server, the essence is to use json – server quick start a Mock server, and then in the config/index/dev/proxyTable agent in the Mock request to the server.

For details about the configuration process, see jSON-server configuration

EasyMock also provides a convenient way to mock data without having to build your own mock environment, which is pretty cool