preface

Write technology blog for the first time a big rookie, do not know where to start, as long as it is helpless pain code farmers, will masturbate code to write bugs on everything. However, I still want to write something about front-end technology. On the one hand, I can improve my writing level, and on the other hand, I can deepen my mastery of the existing front-end knowledge and prepare for the study of new cutting-edge technology. More to learn to review, think, summarize. I searched and decided to take out a small project I did in my spare time two years ago. After my own front-end framework version upgrade and architecture improvement of this project, it is available for the front-end beginners to learn and practice. At the end of the article, github source address will be attached for download and reference. Welcome to make fun of it and mention issue & Star. Let’s start by looking at the project architecture of multi-page application development.

Online demo address: http://106.55.168.13:8090/woyouzhe/

The project architecture

│ ├─public │ Favicon. Ico │ index. HTML │ share.png │ ├─ Favicon ├─ SRC │ ├─assets │ │ ├─ CSS │ │ ├─img │ │ ├─ js │ api.js // ├─ SRC │ ├─assets │ │ ├─ CSS │ │ ├─img │ │ ├─ js │ api.js // Encapsulate all the API interface method is called │ │ common. Js / / js methods │ │ export. Js / / external call unity export │ │ fastclick. Js / / move the click event processing delay │ │ network. The js / / │ │ ├─ Components │ │ Backtop. vue // Go back to the top component │ │ CategoryList. vue // Category component │ │ Url.js // Automatic Deployment server environment │ ├─ Components │ backtop. vue // Category component │ ├─ categoryList Vue // error pop-up message component │ │ jumpCoupon. Vue // jumpCoupon │ │ loading. Vue // page initialization animation component │ │ qrcodePop │ shopList. Vue / / commodity list component │ │ soldOut. Vue / / request data error display placeholder figure │ ├ ─ mock │ │ index. The js / / introduce mockjs simulated data │ └ ─ pages │ ├ ─ coupon │ │ │ │ coupon. Js // coupon page entry file, Load all kinds of public components │ │ coupon. Vue / / coupon redemption page │ ├ ─ the detail │ │ detail. HTML / / commodity details structure │ │ detail. Js / / commodity details entry documents, │ ├─ Index │ ├.js │ ├.js │ ├.js │ ├.js │ ├.js │ ├.js │ ├.js │ ├.js │ ├.js │ │ ├ ─search │ search.js │ ├ ─ sci-imp // ├ ─ sci-imp // ├ ─ sci-imp // ├ ─ sci-imp // │ ├ ─ imp (search. Vue) ├ ─ imp (search. Vue) ├ ─ imp (searchCopy the code

Technology stack

  • vue2.6
  • axios
  • webpack
  • ES6/7
  • flex
  • rem
  • mockjs

Function module

  • Home page round broadcast map
  • List of goods
  • Return to the top
  • Category, fuzzy search
  • Qr code public Account
  • Details page Display
  • Guess you like
  • Check and get coupons
  • Copy coupon link
  • Moments to share tips

The preparatory work

  1. Windows 7/10 system
  2. Download and install NodeJS V9 + nodejs.org/zh-cn/
  3. Code editor tool Sublime Text 2/3

Setting up the development environment

  1. Open the command line window and enter node -v to check. If the version number appears, the installation is successful, as shown in the following figure:
  2. Use the following command to install vuE-cli3
NPM install -g@vue /cli@3.11. 0
# OR
yarn global add @vue/cli
Copy the code

  1. After installation, check vUE version as shown below:
vue -V
Copy the code

  1. Vue-cli3 create and run the project
vue create woyouzhe
cd woyouzhe
npm run serve
Copy the code

Type in the browser address bar:http://localhost:8080/

  1. The development of the configuration

After creating a project with vue-cli3 scaffolding, since the webpack configuration is hidden, when you need to overwrite the original configuration, you need to create a new vue.config.js file in the root directory of the project to configure the new configuration as follows (with notes) :

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production'

module.exports = {
    publicPath: isProduction ? '/dist/' : '/'.// The URL of the production and development environment deployed: the current environment can be distinguished
    lintOnSave: false.// Whether esLint checks when code is saved
  	productionSourceMap: false.// Whether to generate the sourceMap file when building the production package, false will speed up the build
  	devServer: { // webpack-dev-server configuration
	    port: '8090'./ / the port number
	    https: false./ / close the HTTPS
	    hotOnly: false.// Cancel hot updates
	    // proxy: {// use proxy
	    // '/api': {
	    // target: '//www.woyouzhe.com', // target proxy server address
	    // changeOrigin: true, // allows cross-domain
	    // pathRewrite:{
	    // '^/ API ': '// override path. If override is required, prefix/API to the call interface instead of target
	    / /}
	    / /}
	    // }
	},
	// WebPack is configured manually
	configureWebpack: (config) = > {
		if (isProduction) {
			// Unpack the webpack warning
			config.performance = {
		      	hints: 'error'.maxAssetSize: 300000.// The maximum size of the generated file, an integer in bytes
		      	maxEntrypointSize: 500000.// The maximum volume of the entry point, an integer in bytes
            	assetFilter: function(assetFilename) { // Give only performance hints for js files
          			return assetFilename.endsWith('.js');
				}
			}

			config.plugins.push(
		        new UglifyJsPlugin({
		         	uglifyOptions: {
			          	compress: {
			            	drop_debugger: true.// The production environment automatically deletes the debugger
			            	drop_console: true.// The production environment automatically deletes the console
			          	},
			           	warnings: false // Delete useless code without warning
		         	},
		         	sourceMap: false.// Turn off the error message location mapping to the module
		         	parallel: true.// Enable multiple processes to run in parallel}))}}}Copy the code

For multi-page configuration, create a vue.util.js file in the root directory of the project as follows:

const path = require('path')
const glob = require('glob')
const startPath = '/src/pages/'
const pagePath = path.resolve(__dirname, '. ' + startPath)

exports.pages = function () {
  let entryFiles = glob.sync(pagePath + '/**/*.html')
  let obj = {}

  entryFiles.forEach(filePath= > {
    let dirPath = filePath.substring(0, filePath.lastIndexOf('/'))
    let dirName = dirPath.substring(dirPath.lastIndexOf('/') + 1)
    let filename = filePath.substring(filePath.lastIndexOf(startPath) + startPath.length, filePath.lastIndexOf('/'))
    
    if (filename.endsWith(dirName)) {
      obj[filename] = {
        entry: filePath.substring(0, filePath.lastIndexOf('.html')) + '.js'.template: filePath.substring(0, filePath.lastIndexOf('.html')) + '.html'}}})return obj
}
Copy the code

After the configuration is complete, import vue.util.js in vue.config.js file, as shown below:After multi-page configuration is completed, create pages folder under SRC folder, where each page module is placed, and each interface consists of HTML, JS and Vue, as shown below:

  1. Public styles, pictures and JS are stored in the/SRC /assets/ folder as shown below:

Url. Js is the automatic deployment of production environment and development test environment server address, the code is as follows:

let baseUrl = ' '

if (process.env.NODE_ENV == 'development') {
  console.log('dev')
  // Development, test environment
  baseUrl = '//yapi.demo.qunar.com/mock/95397/api'
} else if (process.env.NODE_ENV == 'production') {
  console.log('prod')
  // Production environment
  baseUrl = '//www.woyouzhe.com/api'
}
export {
  baseUrl
}
Copy the code

Network.js is an axios wrapper and interceptor configuration. Install AXIos first and then import network.js as follows:

npm install -S axios
Copy the code
import axios from 'axios'
import { baseUrl } from './url'

let service = axios.create({
	baseURL: baseUrl, // Request the prefix
	timeout: 55000.// Request timeout
})

// Set post to the default content-type
service.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';

// Add request interceptor
service.interceptors.request.use(
	config= > {
		// We can add the head section here
		return config
	}, 
	err= > {

		// Request error handling
		return Promise.reject(err)
})
// Add a response interceptor
service.interceptors.response.use(
	response= > {

		let { data } = response

		return data
	}, 
	err= > {
		// Response error handling
		return Promise.reject(err)
})

export default service
Copy the code

API. Js encapsulates all API interface call methods. We will explain how to call these methods and get the data returned by the server.

import network from './network'
import { baseUrl } from './url'

// Item list interface
export function getShopList(params) {
  return network({
    url: '/shoplist'.method: 'get',
    params
  });
}
Copy the code

Common.js is a common js method with the following code:

let Rxports = {
	// The first argument to the callback is the index or key name, and the second argument is the element or key value
    each: function (obj, fn) {
    	var me = this;
        if (obj) { // exclude null, undefined
            var i = 0
            if (me.isArrayLike(obj)) {
                for (var n = obj.length; i < n; i++) {
                    if (fn(i, obj[i]) === false)
                        break}}else {
                for (i in obj) {
                    if (obj.hasOwnProperty(i) && fn(i, obj[i]) === false) {
                        break}}}}},// Get url parameters
	getUrlParam: function () {
        var url = window.location.search, // Get the "?" in the url The string following the character
        theRequest = new Object(a);if (url.indexOf("?") != -1) {   
          var str = url.substr(1), strs = str.split("&");   
          for(var i = 0; i < strs.length; i ++) {
            theRequest[strs[i].split("=") [0]] = decodeURI(strs[i].split("=") [1]); }}return theRequest; 
    },
    // The page unit is rem
	rem: function () {
        var docEl = document.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function () {
            var clientWidth = docEl.clientWidth;
            if(! clientWidth)return;
            if (clientWidth >= 750) {
                docEl.style.fontSize = '100px';
            } else {
                docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'; }}; recalc();window.addEventListener(resizeEvt, recalc, false);
    },
    // Customize the modal box
    modalHelper: {
    	scrollTop: ' '.bodyCls: 'modal-open'.srcollBody: (document.scrollingElement || document.body),
    	afterOpen: function() {
    		var me = this;
      		this.scrollTop = this.srcollBody.scrollTop;
      		document.body.classList.add(me.bodyCls);
      		document.body.style.top = -this.scrollTop + 'px';
    	},
    	beforeClose: function () {
    		var me = this;
      		document.body.classList.remove(me.bodyCls);
      		this.srcollBody.scrollTop = this.scrollTop;
            document.body.style.top = '0'; }},// remove whitespace
    trim: function (strs) { 
        return strs.replace(/(^\s*)|(\s*$)/g.' '); }}export default Rxports
Copy the code

Fastclick. js is to process the mobile terminal click event, there is 300ms delay, you can directly install the introduction of use, I am directly download JS plug-in to local re-introduction.

/ / installation
npm install -S fastclick
/ / introduction
import FastClick from 'fastclick'
/ / use
FastClick.attach(document.body);
Copy the code

Export.js is the unified exit of the external call module, and the code is as follows:

import '.. /css/common.css'

import C from './common'

// Solve the click 300ms delay problem
import FastClick from './fastclick'

// FastClick.attach(document.body);! (function(){
    new FastClick(document.body)
 })

export default C
Copy the code

The above basic architecture is completed, and finally to enter the page function development, the mood is very cold, the day of knocking code has just begun. Before general development projects, it is necessary to analyze page requirements, which functional modules there are, technology selection, whether there are technical difficulties (whether it can be replaced), which components can be reused, mobile phone adaptation, front-end performance considerations, whether multiple people collaborate in development, and API interface rules agreed with the back-end, etc. Time flies, it’s 2 am, so I’ll stop there.

Like can pay attention to the author public number [lazy code farmers], we learn together progress…

Next: juejin.cn/post/687740…

Github source address: github.com/jackchen012… Welcome Star!