这里是创建移动端项目
【Vue】Vue2.x创建项目全程讲解,保姆级教程,手把手教,Vue2怎么创建项目(上)
【Vue】Vue2创建移动端项目实战教程,创建移动端项目保姆级教程,接上一篇创建Vue2项目(中)
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
请先看前两篇上
和中
,上篇为创建项目,中篇为适配移动端,下篇为引入组件以及配置选项
传送门 Vant 轻量、可靠的移动端 Vue 组件库
我这里是vue2项目,如果是你的项目是vue3的话,说明你已经对vue2有了解了,这里仅供参考vue2的教程
# Vue 3 项目,安装最新版 Vant:
npm i vant -S
# Vue 2 项目,安装 Vant 2:
npm i vant@latest-v2 -S
按需引入和手动引入请看 vant官方写法
全部引入,打开main.js
文件
// 引入vantUI
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
运行项目 npm run serve
修改views下的Home.vue页面为如下代码
<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>
虽然有移动端适配,但是像h2这种标签,你不去给px大小,它好像不一定会转化,就还是pc端大小
打开src/App.vue,删除里面的默认样式
最后保留为如下代码
<template>
<router-view />
template>
在src目录下新建styles文件夹
,然后在文件夹下新建一个base.css,代码如下
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;
}
这个是简单版,复杂的可参考 通用css样式模板,CSS 通用样式总结
在styles新建index.css文件
内容如下
@import url(./base.css);
// 自定义基础样式库
import './styles/index.css'
一般情况ui设计图是750px宽度,vant是基于375,当你在ui设计图上面的尺寸为16px时,你需要设置为32px,才能与设计图一致。
传送门axios中文文档|axios中文网
npm install axios -S
在src目录下创建文件夹 utils
在里面新建一个request.js
文件
我这里考虑到请求需要携带token,以及生产环境和开发环境的配置,
request.js我直接贴出来,不作解释,都有注释,详细可参考若依项目,很多脚手架功能都是来自于若依后台系统
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
不着急,慢慢来
在utils文件夹下创建一个auth.js文件
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)
}
这里需要安装一个插件
npm install --save js-cookie
在utils文件夹下创建一个errorCode.js文件
export default {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}
在src外面创建文件名为 .env.development
#模式
NODE_ENV = 'development'
# // 通过"VUE_APP_MODE"变量来区分环境
VUE_APP_MODE = 'development'
# 请求路径
VUE_APP_BASE_API = '/dev-api'
# 这是开发环境,未上线
# ******************* ** ** **
# ** ** ****************
# ** ** **
# ******************* ************
# ** ** *** **
# ** ** ** ** **
# ** ** ** ***
# ** ** ** ** ***
在src外面创建文件名为 .env.production
#模式
NODE_ENV = 'production'
#通过"VUE_APP_MODE"变量来区分环境
VUE_APP_MODE = 'production'
#api地址
VUE_APP_BASE_API = '/prod-api'
# 这是上线环境,已投入使用
环境配置里面的VUE_APP_BASE_API
为代理请求,可更改,这个东西看后端怎么调用或者修改吧
例如我发起了一个列表请求,这个192.168.1.6是我的电脑ip,后端java的电脑ip例如是192.168.1.7
我就通过/dev-api请求到他的电脑上的接口
与package.json同级
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
}
这一段代码用到了compression-webpack-plugin
,项目中没有,要进行安装,否则会报红
这个东西有版本问题,我直接下载了最新版10.0.0,结果项目运行不起来,然后我就找到了以前旧项目的版本
版本我已经指定好了,直接安装即可。
npm install [email protected] --save-dev
由于vue的特性
,修改env,vue.config.js,项目是需要重启的。
在src目录下创建一个文件夹【api】,在api下创建test.js用作测试,后续写其他接口都是这样
先集成在api文件夹里,然后再不同的vue页面引入
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'
})
}
在Home.vue页面中引入
import { listComment } from "@/api/test.js"
<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>
同理,引入该js中其他方法只需要往后面加就是了
import { listComment , ***list , ***del , ...... } from "@/api/test.js"
每次打开项目都需要手动去写npm run serve,太麻烦了,这里集成了一个bin脚本
与src同级,建立一个文件夹,名字为bin
@echo off
echo.
echo [信息] 打包Web工程,生成dist文件。
echo.
%~d0
cd %~dp0
cd ..
npm run build
pause
@echo off
echo.
echo [信息] 安装Web工程,生成node_modules文件。
echo.
%~d0
cd %~dp0
cd ..
npm install --registry=https://registry.npm.taobao.org
pause
@echo off
echo.
echo [信息] 使用 Vue CLI 命令运行 Web 工程。
echo.
%~d0
cd %~dp0
cd ..
npm run serve
pause
先建一个js然后写进去再改后缀名,或者直接建这个名字然后用VSCode打开编辑。
双击即可运行,如果npm run dev是你的运行方式, 修改里面的server为dev就好了。
很好的一个移动端项目脚手架,axios、环境、适配,都做好了。vuex这个可以用若依的,也可以自己写
vuex有两种,一种没有子模块,没有子模块的,直接在它的store/index.js里面写。
如果有子模块呢,就是子模块引入到这个父模块,父模块在modules里面注册一下。在vue页面中引入就会多一层modules模块。
下面这个就是我自己写的,简单版的,是有子模块的。
vuex的多模块用法简单版
由于这个项目我建的时候选择的是scss渲染器
,所以不是less渲染器。重新建的时候选择scss with dart-scss就好了,或者你装了less再装一下scss也行。全篇下来没有写到关于less或scss的代码