Writing in the front

In this blog, I will introduce the architecture idea of VUE to you. Of course, this is just a summary of the VUE architecture based on the projects I encountered. This is a small round I found.

All right, let’s start talking!

Refactoring is introduced

  1. First refactoring: Centralized Ajax requests
  2. Second refactoring: Use the class inheritance architecture
  3. Third refactoring: Use the configuration table schema
  4. Fourth refactoring: Use class inheritance + singleton architecture

2019.9.16 The git address is reconstructed last time

Original version

The directory structure

├ ─ ─ the SRC directory / / production │ ├ ─ ─ the API / / axios │ ├ ─ ─ the components / / component │ │ ├ ─ ─ common / / common components │ │ ├ ─ ─ the admin / / user component │ │ └ ─ ─ seller / / business component │ ├ ─ ─ the router / / routing │ ├ ─ ─ the store / / vuex state manager │ ├ ─ ─ App. Vue / / homepage │ └ ─ ─ main. Js / / Webpack precompiled entranceCopy the code

Code logic

It’s easy to start by going to app.vue and rendering the page based on the different components of the route map, with Ajax requests for each page

Ajax requests look like this

getUserInfo: function() {
    this.axios.get('user/infor')
    .then(res => {
        if (res.data.status) {
            this.user = res.data.data;
        }
    })
    .catch(error => {
        console.log(error);
    });
},
Copy the code

The front-end is refactored for the first time

2018.4.21 Github address: ELm1.0

The directory structure

├ ─ ─ the SRC directory / / production │ ├ ─ ─ the API / / axios │ ├ ─ ─ the components / / component │ ├ ─ ─ the router / / routing │ ├ ─ ─ the store / / vuex state manager │ ├ ─ ─ App. Vue / / ├ ─ ├ ─ main.js // WebpackCopy the code

That’s right, just put ajax requests in the API directory in the index.js file

import axios from 'axios';
import store from '.. /store';

let httpURL = "http://www.xuguobin.club/api/elm/"// This is my server's API interfacelet localURL = 'http://localhost/api/elm/'; // This is the native KOA2 API interface axios.defaults.baseURL =localURL;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

exportDefault {// Get user informationgetUser() {
        return axios.get('user/infor'); }, // get the order getOrders(orderType) {return axios.get('user/order? type='+ orderType); }, // submitOrder submitOrder(order) {return axios.get('user/submit? order='+ order); }, // confirm receipt of goods confirmOrder(orderId) {return axios.get('user/confirm? orderId='+ orderId); }, // submitRating(rating) {return axios.get('user/rating? rating='+ rating); }, // userLogin(user) {return axios.post('user/login',`username=${user.username}&password=${user.password}`); }};Copy the code

By doing this, you’re decoupling the AXIos request from the VUE page! Ajax requests now look like this

getUserInfo: function() {
    this.api.getUser()
    .then(res => {
        if (res.data.status) {
            this.user = res.data.data;
        }
    })
    .catch(error => {
        console.log(error);
    });
},
Copy the code

The front-end is reconstructed for the second time

Github address: Elm2.0

The directory structure

This is a bit of a refactoring overkill, to be fair

├ ─ ─ the SRC directory / / production │ └ ─ ─ axios / / axios | ├ ─ ─ base / / axios template | | ├ ─ ─ base. The js / / axios base class | | └ ─ ─ setting. The js / / status code | └ ─ ─ the user | ├ ─ ─ cache. Js / / request function | └ ─ ─ config. Js / / configuration information | | ├ ─ ─ base / / vue template │ ├ ─ ─ the components / / component | | ├ ─ ─ common / / common components | | └ ─ ─ the admin | | ├ ─ ─ UI. Vue / / output component | | ├ ─ ─ component. The HTML / / template | | ├ ─ ─ component. The js / / script | | └ ─ ─ component. The less / / Style | | │ ├ ─ ─ the router / / routing │ ├ ─ ─ the store / / vuex state manager │ ├ ─ ─ App. Vue / / homepage │ └ ─ ─ the main, js / / Webpack precompiled entranceCopy the code

The first refactoring separated the AXIos request from the page, but the status code was validated after each request and error messages were handled.

There’s no need to visit every page. These common operations can be put together in axios’s base class

import axios from 'axios'
import setting from './setting'

let httpURL = "http://www.xuguobin.club/api/elm/"// This is my server's API interfacelet localURL = 'http://localhost/api/elm/'; // This is the native KOA2 API interface axios.defaults.baseURL = httpURL; axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

export default class AxiosCache {
	constructor() {
		this.__config = {}
		this.__setting = setting;
		this.init();
	}

	init() {
		this.doFlushSetting(CACHE_KEY, )
	}

	doFlushSetting(key, conf) {
		if(! key && typeof key ! = ='string') {
			return} this.__config[key] = conf} /* Judge status code */ resultJudge(code) {return/* sendRequest data */ sendRequest(key, options) {let send = this.__config[this.settingKey][key];
		let self = this;
		let baseURL = send.url;
		send.method == 'get'
			? options.data && (send.url += options.data)
			: send.data = options.data
		axios(send)
			.then(function (response) {
				send.url = baseURL;
				if (self.resultJudge(response.data.status)) {
					options.success(response.data.data)
				} else {
					options.fail
						? options.fail(response.data.data)
						: self.handleErrorCase(response.data.status)
				}
			}).catch(function(error) {self.handleErrorCase(error)})} /* Handle error message */ handleErrorCase(error) {if (typeof error == 'Number') {
			console.log(error)
		} else {
			alert(error)
		}
	}
}
Copy the code

When you send a request, that’s all you need

getUSer: function() {
     this.userCache.getUser({
         success: res => this.user = res
     })
},
Copy the code

Isn’t that neat? This further decouples the AXIos operation. You can compare the two versions of ELM1 and ELM2 on Github, and you will definitely learn something.

The architectural pursuit of the front end is perfect reuse and decoupling

The front-end was reconstructed for the third time. Procedure

Github Address: Elm3.0

It’s probably not optimized much, but it gives you an idea

The axios processing logic in the ELM2 version is: Encapsulating a base class of AxiosCache that has some common methods, other AXIos objects inherit this base class and instantiate it in their own pages, instantiating a UserCache if the page requires a user-specific interface, and a UserCache if another page is also useful. Repetitive instantiation strikes me as a waste of performance. So I came up with another axios construct that doesn’t use class inheritance and instantiation

The structure of ELM3 is as follows

├ ─ ─ axios / / axios | ├ ─ ─ index. The js / / axios configuration table | ├ ─ ─ base / / axios public parts | | ├ ─ ─ index. The js / / axios public methods | | └ ─ ─ setting. Js / / a status code | └ ─ ─ the user | ├ ─ ─ cache. | js / / request function └ ─ ─ config. Js / / configuration informationCopy the code

The axios processing logic in ELM3 is as follows: a configuration table is formed by importing the configuration information and status codes of each Cache into index.js in the AXIos directory

// Import setting from'./base/setting'// Import config table import userConfig from'./user/config';
import goodConfig from './good/config';
import sellerConfig from './seller/config';

export default {
    __setting: setting,
    __config:  {
        'user_cache_key': userConfig,
        'good_cache_key': goodConfig,
        'seller_cache_key': sellerConfig
    }
}

Copy the code

Assign this configuration table import to Vue (main.js) :

import axios from '@/axios' 
Vue.$axios = axios;
Copy the code

In the base directory index.js, only public methods are kept (I’m using Promise here)

import axios from 'axios'
import Vue from 'vue'

let httpURL = "http://www.xuguobin.club/api/elm/"// This is my server's API interfacelet localURL = 'http://localhost/api/elm/'; // This is the native KOA2 API interface axios.defaults.baseURL = httpURL; axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; // Determine the status codefunction resultJudge(code) {
	returnCode} // Handle error public methodsfunction handleErrorCase(error) {
	if (typeof error == 'Number') {
		console.log(error)
	} else{alert(error)}} // Send requestexport default function sendRequest(settingKey, key, data) {
	let send = Vue.$axios.__config[settingKey][key];
	let baseURL = send.url;
	send.method == 'get'
		? data && (send.url += data)
		: send.data = data;
	return new Promise((resolve,reject) => {
		axios(send)
		.then((res)=>{
			send.url = baseURL;
			resultJudge(res.data.status) ? resolve(res.data.data) : reject(res.data.data);
		}).catch((err)=>{
			handleErrorCase(err)
		});
	});
}
Copy the code

Request functions in other Cache pages

import sendRequest from '.. /base';
const CACHE_KEY = 'good_cache_key'

export default {
	getGood(options) {
		return sendRequest(CACHE_KEY, 'good-getGood',options);
	},
	getGoods(options) {
		return sendRequest(CACHE_KEY, 'good-getGoods',options); }}Copy the code

The advantage of this is that a table of ajax requested information is created when the page is first loaded and stored in Vue.$axios, which is indexed by the table instead of instantiated when the page is used later

The front end was reconstructed for the fourth time

Github address: Elm3.1

One problem with the use of the inheritance architecture in elm2.0 was discussed earlier: repeated instantiations resulted in wasted performance. So use another configuration table structure of AXIOS that doesn’t use class inheritance and instantiation, version ELm3.0. In fact, the problem can be solved by singleton mode, but I was too surprised at the time.

GoodCache, for example

import BaseCache from '.. /base/base';
import config from './config';
const CACHE_KEY = 'good_cache_key';

class GoodCache extends BaseCache {
  constructor() {
    super();
    this.settingKey = CACHE_KEY;
  }

  init() {
    this.doFlushSetting(CACHE_KEY, config);
  }

  getGood(options) {
    this.sendRequest('good-getGood', options);
  }

  getGoods(options) {
    this.sendRequest('good-getGoods', options); }}export default (function() {
  let goodCache;
  return function() {
    if(! goodCache) { goodCache = new GoodCache(); }returngoodCache; }; }) ();Copy the code

Introduced use in other pages:

import GoodCache from '@/axios/good/cache';

created: function() {
    this.goodCache = GoodCache();
    this.getGood();
}
Copy the code

No matter how many pages call the API in GoodCache, GoodCache is instantiated only once, and only one GoodCache object exists globally.

Fifth front-end refactoring?

To be continued…… You have good architecture and you are welcome to fork my Master version! ^_^