[Vue] Practical tutorial on creating mobile projects with Vue2, nanny-level tutorial on creating mobile projects, setting up axios, utils toolkit, vue.fonfig.js configuration items (Part 2)

Table of Contents of Series Articles

这里是创建移动端项目
[Vue] Full explanation of the creation of Vue2
. Project (Part 2)
[Vue] Practical tutorial on creating a mobile project with Vue2, nanny-level tutorial on creating a mobile project, setting up axios, utils toolkit, vue.fonfig.js configuration items (Part 2)


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


Preface

Please read the first two articles . The first article is about creating a project, the middle article is about adapting to mobile terminals, and the next article is about introducing components and configuration options.


1. Install vant2

Portal Vant is a lightweight and reliable mobile Vue component library

1. Import the library

My project here is vue2. If your project is vue3, it means you already know about vue2. This is only for reference vue2 tutorial.

# Vue 3 项目,安装最新版 Vant:
npm i vant -S

# Vue 2 项目,安装 Vant 2
npm i vant@latest-v2 -S

2.Introduce components

For on-demand import and manual import , please see the official writing method of vant.

Import all, open main.jsthe file

// 引入vantUI
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);

Insert image description here

Run the project npm run serve

3. Check components and adaptation

Modify the Home.vue page under views to the following code

<template>
  <div class="home">
    <van-button type="primary">主要按钮</van-button>
    <van-button type="info">信息按钮</van-button>
    <van-button type="default">默认按钮</van-button>
    <van-button type="warning">警告按钮</van-button>
    <van-button type="danger">危险按钮</van-button>
  </div>
</template>

<script>
// @ is an alias to /src

export default {
      
      
  name: 'Home',
  components: {
      
      

  }
}
</script>

The effect is as shown in the figure
Insert image description here
Insert image description here

Although there is mobile adaptation, if you don't give a px size to a tag like h2, it doesn't seem to necessarily convert, and it will still be the PC size.

2. Set the style

1. Clear app.vue default style

Open src/App.vue, delete the default style inside,
and finally retain the following code

<template>
  <router-view />
</template>

2. Create a new global style

在src目录下新建styles文件夹, and then create a new base.css in the folder, the code is as follows

body,ul{
    
    
	margin: 0;
	padding: 0;
}
ul{
    
    
	list-style: none;
}
h1,h2,h3,h4,h5,p,span{
    
    
	margin: 0;
	/* font-family: 'PingFang SC'; */
	font-family: PingFang SC-Heavy, PingFang SC;
}
a{
    
    
	text-decoration: none;
	color: #333;
}
img{
    
    
	vertical-align: middle;
}

This is a simple version. For more complex ones, please refer to the general CSS style template and CSS general style summary.

3.Introduce global styles

Create a new index.css file in styles
with the following content

@import url(./base.css);

Insert image description here
In main.js, introduce the index.css file

// 自定义基础样式库
import './styles/index.css'

The effect after introduction is as shown below
Insert image description here

Generally, the UI design drawing is 750px wide, and vant is based on 375. When your size on the UI design drawing is 16px, you need to set it to 32px to be consistent with the design drawing.


3. Set axios request

1. Download axios and set the request request

Portal axios Chinese documentation | axios Chinese website

npm install axios -S

Create the folder utils in the src directory and create a new file
in itrequest.js

Here I consider that the request needs to carry a token, as well as the configuration of the production environment and development environment.
I posted the request.js directly without explanation. It has comments. For details, please refer to the Ruoyi project. Many scaffolding functions come from the Ruoyi backend. system

import axios from 'axios'
import errorCode from '@/utils/errorCode'
import {
    
    
	getToken
} from '@/utils/auth'

import {
    
    
	Dialog,
	Notify
} from 'vant';

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'

// 创建axios实例
const service = axios.create({
    
    
	// axios中请求配置有baseURL选项,表示请求URL公共部分
	baseURL: process.env.VUE_APP_BASE_API, // 本地后台接口||服务器接口
	// 超时
	timeout: 40000
})
// request拦截器
service.interceptors.request.use(config => {
    
    
	// 是否需要设置 token
	const isToken = (config.headers || {
    
    }).isToken === false
	// config.headers['Authorization'] = sessionStorage.getItem('token') // 让每个请求携带自定义token 请根据实际情况自行修改
	// config.headers['token'] = sessionStorage.getItem('token') // 让每个请求携带自定义token 请根据实际情况自行修改
	config.headers['Authorization'] = 'Bearer ' + getToken()
	// get请求映射params参数
	if (config.method === 'get' && config.params) {
    
    
		let url = config.url + '?';
		for (const propName of Object.keys(config.params)) {
    
    
			const value = config.params[propName];
			var part = encodeURIComponent(propName) + "=";
			if (value !== null && typeof (value) !== "undefined") {
    
    
				if (typeof value === 'object') {
    
    
					for (const key of Object.keys(value)) {
    
    
						let params = propName + '[' + key + ']';
						var subPart = encodeURIComponent(params) + "=";
						url += subPart + encodeURIComponent(value[key]) + "&";
					}
				} else {
    
    
					url += part + encodeURIComponent(value) + "&";
				}
			}
		}
		url = url.slice(0, -1);
		config.params = {
    
    };
		config.url = url;
	}
	return config
}, error => {
    
    
	console.log(error)
	Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
    
    
	// 未设置状态码则默认成功状态
	const code = res.data.code || 200;
	// 获取错误信息
	const msg = errorCode[code] || res.data.msg || errorCode['default']
	// 二进制数据则直接返回
	if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
    
    
		return res.data
	}
	if (code === 401) {
    
    
		return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
	} else if (code === 402) {
    
    
		return Promise.reject(new Error(msg))
	} else if (code === 403) {
    
    
		return Promise.reject(new Error(msg))
	} else if (code === 500) {
    
    
		Notify({
    
    
			type: 'danger',
			message: msg
		});
		return Promise.reject(new Error(msg))
	} else if (code === 601) {
    
    
		Notify({
    
    
			type: 'warning',
			message: msg
		});
		return Promise.reject('error')
	} else if (code !== 200) {
    
    
		Dialog({
    
    
			title: '错误',
			message: msg
		});
		return Promise.reject('error')
	} else {
    
    
		return res.data
	}
}, error => {
    
    
	console.log('err' + error)
	let {
    
    
		message
	} = error;
	if (message == "Network Error") {
    
    
		message = "后端接口连接异常";
	} else if (message.includes("timeout")) {
    
    
		message = "系统接口请求超时";
	} else if (message.includes("Request failed with status code")) {
    
    
		message = "系统接口" + message.substr(message.length - 3) + "异常"; // 例如502异常
		// message = "系统更新服务中,请稍后重试";
	}
	// 弹出报错信息
	Notify({
    
    
		message: message,
		type: 'danger',
		duration: 5 * 1000,
	});
	return Promise.reject(error)
}
)


// 使用a标签下载
export function fileDown(blobUrl, filename) {
    
    
	const a = document.createElement("a");
	if (!a.click) {
    
    
		throw new Error('DownloadManager: "a.click()" is not supported.');
	}
	a.href = blobUrl;
	a.target = "_parent";
	if ("download" in a) {
    
    
		a.download = filename;
	}
	(document.body || document.documentElement).append(a);
	a.click();
	a.remove();
}

export default service

  • The above code lacks a getToken method
  • There is also an errorCode variable missing

不着急,慢慢来

2. Introduce getToken method

Create an auth.js file in the utils folder

import Cookies from 'js-cookie'

const TokenKey = 'Admin-Token'

export function getToken() {
    
    
  return Cookies.get(TokenKey)
}

export function setToken(token) {
    
    
  // 设置60分钟后过期
  const inFifteenMinutes = new Date(new Date().getTime() + 60 * 60 * 1000);
  return Cookies.set(TokenKey, token, {
    
     expires: inFifteenMinutes })
}

export function removeToken() {
    
    
  return Cookies.remove(TokenKey)
}

You need to install a plug-in here

npm install --save js-cookie

3. Introduce errorCode variable

Create an errorCode.js file in the utils folder

export default {
    
    
  '401': '认证失败,无法访问系统资源',
  '403': '当前操作没有权限',
  '404': '访问资源不存在',
  'default': '系统未知错误,请反馈给管理员'
}

4. Set up env environment

1. Create local environment dev

Create a file named outside src.env.development

#模式
NODE_ENV = 'development'
#  // 通过"VUE_APP_MODE"变量来区分环境
VUE_APP_MODE = 'development'

# 请求路径
VUE_APP_BASE_API = '/dev-api'


# 这是开发环境,未上线

#		*******************			**   **		**
#			**		**			   ****************
#			**		**					**
#		*******************			   ************
#			**		**				  ***	    **
#			**		**				 **  **    **
#		   **		**				**	    ***
#		  **		**			   **	 **    ***

2. Create server environment prod

Create a file named outside src.env.production

#模式
NODE_ENV = 'production'

#通过"VUE_APP_MODE"变量来区分环境
VUE_APP_MODE = 'production'

#api地址
VUE_APP_BASE_API = '/prod-api'

# 这是上线环境,已投入使用

The environment configuration is VUE_APP_BASE_APIproxy request, which can be changed. It depends on how the backend calls or modifies it.
Insert image description here
For example, I initiated a list request. This 192.168.1.6 is my computer IP. The computer IP of the backend Java is 192.168.1.7, for example.

I requested the interface on his computer through /dev-api

五、vue.config.js

Same level as package.json

1. Create vue.config.js

const webpack = require('webpack')
const path = require("path")

const CompressionPlugin = require('compression-webpack-plugin')

module.exports = {
    
    
	lintOnSave: false,
	devServer: {
    
    
		port: 8088,
		host: '0.0.0.0',
		open: true,
		proxy: {
    
    
			[process.env.VUE_APP_BASE_API]: {
    
    
				target: `http://192.168.1.66:8080`,
				changeOrigin: true,
				pathRewrite: {
    
    
					['^' + process.env.VUE_APP_BASE_API]: ''
				}
			},
		},
		historyApiFallback: true, // 设置了当服务端收到 404 请求时,将会返回 index.html 文件
	},
	configureWebpack: {
    
    
		resolve: {
    
    
			alias: {
    
    
				'@': path.resolve(__dirname, 'src'),
				'assets': '@/assets'
			}
		},
		plugins: [
			// http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
			new CompressionPlugin({
    
    
				cache: false,                   // 不启用文件缓存
				test: /\.(js|css|html)?$/i,     // 压缩文件格式
				filename: '[path].gz[query]',   // 压缩后的文件名
				algorithm: 'gzip',              // 使用gzip压缩
				minRatio: 0.8                   // 压缩率小于1才会压缩
			}),
			// maxChunks:使用大于或等于 1 的值,来限制 chunk 的最大数量。使用 1 防止添加任何其他额外的 chunk,这是因为 entry/main chunk 也会包含在计数之中。
			//minChunkSize: 设置 chunk 的最小大小。
			// 限制打包的个数(减少打包生成的js文件和css文件)
			new webpack.optimize.LimitChunkCountPlugin({
    
    
				maxChunks: 10,
				minChunkSize: 100
			})
		],
	},
	publicPath: "/",
	assetsDir: './',
	assetsDir: 'static', // 整合css和js到这里
	outputDir: 'app', // 打包名称,例如默认为dist
}

This piece of code is used compression-webpack-plugin, but it is not included in the project. It needs to be installed, otherwise it will report red.

There is a version problem with this thing. I directly downloaded the latest version 10.0.0, but the project could not run. Then I found the version of the old project.

I have already specified the version and can install it directly.

npm install [email protected] --save-dev

After installation, please check the configuration in package.json
Insert image description here

由于vue的特性, modify env, vue.config.js, the project needs to be restarted.


2. Modify the background interface address

Insert image description here
This target, here is your local backend java development address

6. Write api request

1.Create an interface

Create a folder [api] in the src directory, and create test.js under the api for testing. This is how you will write other interfaces later.
Integrate it into the api folder first, and then introduce it on different vue pages.

import request from '@/utils/request'
// 查询常用意见列表
export function listComment(query) {
    
    
    return request({
    
    
        url: '/flow/comment/list',
        method: 'get',
        params: query
    })
}
// 查询常用意见详细
export function getComment(id) {
    
    
    return request({
    
    
        url: '/flow/comment/' + id,
        method: 'get'
    })
}
// 新增常用意见
export function addComment(data) {
    
    
    return request({
    
    
        url: '/flow/comment',
        method: 'post',
        data: data
    })
}
// 修改常用意见
export function updateComment(data) {
    
    
    return request({
    
    
        url: '/flow/comment',
        method: 'put',
        data: data
    })
}
// 删除常用意见
export function delComment(id) {
    
    
    return request({
    
    
        url: '/flow/comment/' + id,
        method: 'delete'
    })
}

Insert image description here

2.Introduce api methods into vue page

Introduced in Home.vue page

import {
    
     listComment } from "@/api/test.js"

Insert image description here
Then write the methods method and request it in created

<template>
  <div class="home">
    <h1>这是h1标签</h1>
    <h2>这是h2标签</h2>
    <h3>这是h3标签</h3>
    <h4>这是h4标签</h4>
    <h5>这是h5标签</h5>
    <van-button type="primary">主要按钮</van-button>
    <van-button type="info">信息按钮</van-button>
    <van-button type="default">默认按钮</van-button>
    <van-button type="warning">警告按钮</van-button>
    <van-button type="danger">危险按钮</van-button>
  </div>
</template>

<script>
// @ is an alias to /src

import {
      
       listComment } from "@/api/test.js"
export default {
      
      
  name: 'Home',
  components: {
      
      

  },
  data() {
      
      
    return {
      
      

    }
  },
  created() {
      
      
    this.getList()
  },
  methods: {
      
      
    // 获取列表
    getList() {
      
      
      listComment().then(res => {
      
      

      })
    }
  }
}
</script>

Open the f12 console and view network requests
Insert image description here

Insert image description here
I have already requested the data here


In the same way, to introduce other methods in this js, you only need to add them later.

import {
    
     listComment , ***list , ***del , ...... } from "@/api/test.js"

Then there are different js that need to be divided into different js packages, as shown below
Insert image description here

7. Bin script file, run with one click

Every time you open a project, you need to manually write npm run serve, which is too troublesome. A bin script is integrated here
. It is at the same level as src and creates a folder named bin.
Insert image description here

1. Packaging – build.bat

@echo off
echo.
echo [信息] 打包Web工程,生成dist文件。
echo.

%~d0
cd %~dp0

cd ..
npm run build

pause

2. Download dependencies – package.bat

@echo off
echo.
echo [信息] 安装Web工程,生成node_modules文件。
echo.

%~d0
cd %~dp0

cd ..
npm install --registry=https://registry.npm.taobao.org

pause

3. Run – run-web.bat

@echo off
echo.
echo [信息] 使用 Vue CLI 命令运行 Web 工程。
echo.

%~d0
cd %~dp0

cd ..
npm run serve

pause

Insert image description here
Create a js first and then write it in and then change the suffix name, or create the name directly and open it for editing with VSCode.

Double-click to run. If npm run dev is your running method, just modify the server inside to dev.

Summarize

gitee link, the portal has been made public

Insert image description here

A very good mobile terminal project scaffolding, axios, environment, and adaptation are all ready. You can use Ruoyi for vuex, or you can write it yourself

There are two types of vuex, one has no submodules, and the one without submodules can be written directly in its store/index.js.
If there is a submodule, the submodule is imported into the parent module, and the parent module is registered in modules. When introduced into the vue page, there will be an additional layer of modules.

The following is what I wrote myself, a simple version with sub-modules.
Simple version of multi-module usage of vuex

由于这个项目我建的时候选择的是scss渲染器, so not the less renderer. When rebuilding, just choose scss with dart-scss , or you can install less and then install scss. There is no code about less or scss written in the whole article.

Guess you like

Origin blog.csdn.net/qq_51055690/article/details/132270285