技术选型
公司现在需要开发移动端的h5,使用现在比较流行的vue 2.0开发,使用的脚手架是Vant2,网络访问使用的是axios,路由跳转使用的是vue-router,开发工具是vscode,作为一个安卓开发程序员,对vue是不熟悉的,好在把环境搭建起来了,通过博客记录一下 Vant 2 vue cli vue vue中使用axios最详细教程 vue router
环境搭建
引入库
我这里已经安装好了nodejs,并且已经配置好了淘宝镜像
npm config set registry https://registry.npm.taobao.org
。这些配置网上都有,可以自行查询。 vscode不能直接在工具里创建项目,要先创建一个空文件夹,然后通过vscode打开文件夹。 在E:\vueProject文件夹下创建VueForBlog文件夹,使用vscode打开(vscode默认只能打开一个项目,如果想打开多个,可以使用ctrl+shift+n),点击工具栏终端,新建终端,正式开始创建项目 终端输入
npm i vant@latest-v2 -S
再输入
npm install -g @vue/cli
安装完成 打开package.json看一下依赖 创建一个项目
vue create first-vue
这个好像不能用驼峰,我刚开始用firstVue就报错。一般会出现选择项,我这边选择了vue2 创建完成以后,会是这个样子 记住,后边要cd到工程里,否则还是在工程外创建引用之类的 下边用同样的方法,引入axios,router,还有vant需要使用的 postcss-px-to-viewport,postcss-pxtorem,lib-flexible
npm install vue-router@3.0.7 npm install axios npm i -S amfe-flexible npm install postcss postcss-pxtorem --save-dev npm install postcss-px-to-viewport --save-dev npm install --save less-loader less
配置环境
配置vant 的基础样式,方便引用vant的组件。在first\src\assets\style\下创建theme.less,内容
@black: #4A4A4A;
@white: #fff;
@gray-1: #f7f8fa;
@gray-2: #f2f3f5;
@gray-3: #ebedf0;
@gray-4: #dcdee0;
@gray-5: #c8c9cc;
@gray-6: #969799;
@gray-7: #646566;
@gray-8: #323233;
@gray-9: #9B9B9B;
@red: #FF4473;
@price:#FF4D4F ;
@blue: #4D7BF3;
@orange: #ff976a;
@orange-dark: #ed6a0c;
@orange-light: #fffbe8;
@green: #68C2BD;
@yellow:#E6A23C;
@gradient-red: linear-gradient(to right, #ff6034, #FF4473);
@gradient-orange: linear-gradient(to right, #ffd01e, #ff8917);
@pagination-item-default-color:@green;
@text-color: @gray-8;
@active-color: @gray-2;
@active-opacity: 0.7;
@disabled-opacity: 0.5;
@background-color: @gray-1;
@background-color-light: #fafafa;
@text-link-color: #576b95;
@padding-base: 4px;
@padding-xs: @padding-base * 2;
@padding-sm: @padding-base * 3;
@padding-md: @padding-base * 4;
@padding-lg: @padding-base * 6;
@padding-xl: @padding-base * 8;
@font-size-xs: 10px;
@font-size-sm: 12px;
@font-size-md: 14px;
@font-size-lg: 16px;
@font-weight-bold: 500;
@line-height-xs: 14px;
@line-height-sm: 18px;
@line-height-md: 20px;
@line-height-lg: 22px;
@base-font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB',
'Microsoft Yahei', sans-serif;
@price-integer-font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial,
sans-serif;
@animation-duration-base: 0.3s;
@animation-duration-fast: 0.2s;
@animation-timing-function-enter: ease-out;
@animation-timing-function-leave: ease-in;
@border-color: @gray-3;
@border-width-base: 1px;
@border-radius-sm: 2px;
@border-radius-md: 4px;
@border-radius-lg: 8px;
@border-radius-max: 999px;
@sidebar-selected-border-color:@green;
@radio-checked-icon-color:@green;
@checkbox-checked-icon-color:@green;
@dialog-confirm-button-text-color:@green;
body{
color: @black;
}
.blue,.blue .van-count-down{
color: @blue;
}
.gray-1{
color:@gray-1;
}
.gray-2{
color:@gray-2;
}
.gray-3{
color:@gray-3;
}
.gray-4{
color:@gray-4;
}
.gray-5{
color:@gray-5;
}
.gray-6{
color:@gray-6;
}
.gray-7{
color: @gray-7;
}
.gray-8{
color:@gray-8;
}
.gray-9{
color:@gray-9
}
.red{
color: @red;
}
.price{
color: @price;
}
.black{
color: @black !important;
}
ul.menzChose li,.contenttimes ul li.timesselect{
border: 1px solid @black;
color: @black;
}
ul.menzChose li.current,.contenttimes ul li.timesselect.current{
border: 1px solid @green;
color: @green;
}
.chosehalf .sure{
background: @green;
border: 1px solid @green;
}
.chosehalf .status.yy{
background: @green;
}
.chosehalf .status.yyn{
background: @gray-9;
}
.chosehalf .info{
background: @gray-9;
border: 1px solid @gray-9;
}
.border-top{
border-top: 1px solid @gray-1;
}
.tip-d{
border: 1px solid @blue;
color: @blue;
}
.back-card-primary{
background: @green;
}
.back-white-step .van-step__icon--active,
.back-white-step .van-step__circle {
background: @green
}
.back-white-step .van-steps p{
color:@gray-9
}
.white-back-list{
color: @black;
}
label.tipsBlue{
background: @blue;
}
.grey{
color: @gray-9;
}
.roundGreen{
background: @green;
}
.roundBlue{
background: @blue;
}
.roundYellow{
background: @yellow;
}
p.noline{
color: @gray-9;
}
.table tr th{
color: @gray-9;
}
同样目录下,创建一个public.css,内容
body {
background-color: #f8f8f9;
min-height: 100vh;
min-width: 100vw;
}
.padding-lr10 {
padding: 0 10px;
}
.phoneContant header .van-nav-bar {
text-align: center;
line-height: 56px;
background: #68c2bd;
}
h3 {
font-size: 16px;
}
.phoneContant header .van-nav-bar .van-icon {
font-size: 20px;
color: #fff;
}
.phoneContant header .van-nav-bar__title {
color: #fff;
}
.contant {
padding: 0 10px;
}
.re {
position: relative;
}
.cardContant {
background: #f5f5f5;
height: 78vh;
width: 100%;
clear: both;
padding: 8px 0;
}
.hosImg {
width: 60px !important;
height: 60px !important;
border-radius: 50%;
}
这里的内容,是根据项目中需要的样式自定义的 在vue.config.js里进行配置
css: {
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
hack: `true; @import "@/assets/style/theme.less";`,
},
},
},
},
},
访问资源路径,有个快捷方法,设置一个符号,用来直接指定到src目录下,比用. 或者.. 方便,还不容易出错,同样在vue.config.js里,@ 就代表src目录
chainWebpack: (config) => {
config.resolve.alias.set("@", resolve("src"));
config.plugin("html").tap((args) => {
args[0].minify = false;
return args;
});
},
vue.config.js全部内容
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
publicPath: "./",
outputDir: "dist",
assetsDir: "static",
lintOnSave: false,
css: {
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
hack: `true; @import "@/assets/style/theme.less";`,
},
},
},
},
},
devServer: {
port: 8080,
},
chainWebpack: (config) => {
config.resolve.alias.set("@", resolve("src"));
config.plugin("html").tap((args) => {
args[0].minify = false;
return args;
});
},
configureWebpack: (config) => {
if (process.env.NODE_ENV === "Production") {
config.plugins.push(
new CompressionWebpackPlugin({
algorithm: "gzip",
test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
threshold: 10240,
minRatio: 0.8,
})
);
}
config.externals = {
};
},
productionSourceMap: false,
pluginOptions: {
},
};
lintOnSave: false, 这个的意思就是关闭语法检查,要不然会很多报错,运行不起来 在first-vue目录下,新建一个.postcssrc.js,在里边配置postcss
module.exports = {
plugins: {
autoprefixer: {
browsers: ["Android >= 4.0", "iOS >= 7"],
},
"postcss-pxtorem": {
rootValue: 37.5,
propList: ["*"],
},
},
};
底部安全区适配 在public目录下的index.html文件配置底部安全区适配
<!DOCTYPE html>
<html lang="en">
<head>
<meta base="/" id="base" />
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover,user-scalable=no"
/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>首页</title>
</head>
<body>
<!-- 开启顶部安全区适配 -->
<van-nav-bar safe-area-inset-top />
<div id="app"></div>
<!-- built files will be auto injected -->
<!-- 开启底部安全区适配 -->
<van-number-keyboard safe-area-inset-bottom />
</body>
</html>
<script>
</script>
src目录下,新建router目录,下边新建index.js,对router进行配置
import Vue from "vue";
import VueRouter from "vue-router";
import { asyncRouterMap } from "@/config/router.config";
Vue.use(VueRouter);
const routes = []
const router = new VueRouter({
routes: routes.concat(asyncRouterMap),
mode: "hash",
});
export default router;
在src的config目录下,新建router.config,这个对应路由和相应的页面
export const asyncRouterMap = [
{
path: "/",
component: () => import("@/components/Header.vue"),
meta: { title: "首页" },
redirect: "/home",
children: [
{
path: "/home",
name: "home",
component: () => import("@/views/Home.vue"),
hidden: true,
meta: { title: "首页" },
},
{
path: "/second",
name: "second",
component: () => import("@/views/Second.vue"),
hidden: true,
meta: { title: "第二页" },
},
],
},
{
path: "*",
redirect: "/home",
hidden: true,
},
];
具体页面,等会创建 对App.vue进行修改
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
#app {
height: 100%;
}
.el-header,
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
line-height: 60px;
}
body > .el-container {
margin-bottom: 40px;
}
</style>
我现在需要对一个头部组件进行封装,因为每个页面都有头部导航栏,所以封装成一个组件 在components目录里,新建Header.vue
<template>
<div class="phoneContant">
<header>
<van-nav-bar
class="personheader"
:fixed="true"
:placeholder="true"
:safe-area-inset-top="true"
:title="$route.meta.title"
left-text=""
:left-arrow="true"
@click-left="back"
/>
</header>
<router-view></router-view>
</div>
</template>
<script>
var config = {
isAndroid: /Android/i.test(navigator.userAgent),
isIos: !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
};
export default {
name: "Headers",
components: {},
data() {
return {
title: "",
};
},
computed: {},
watch: {
$route: {
handler(newRouter, fromRouter) {
},
immediate: true,
},
},
methods: {
back() {
this.$router.go(-1);
return false;
},
},
created() {
let cont = window.history.length;
console.log("window.history.length-----------------roomstep");
console.log(cont);
},
mounted() {
},
beforeCreate() {},
beforeMount() {},
beforeUpdate() {},
updated() {},
beforeDestroy() {},
destroyed() {
},
activated() {},
};
</script>
在main.js里进行引入vant和css样式,以及其他组件
import Vue from 'vue'
import App from './App.vue'
import "@/assets/style/public.css";
import router from "@/router";
import Vant from "vant";
import "vant/lib/index.less";
import "@/assets/style/public.css";
Vue.config.productionTip = false
Vue.use(Vant);
new Vue({
router,
render: h => h(App),
}).$mount('#app')
在src下创建一个views文件夹,新建两个vue,Home.vue和Second.vue,内容很简单 Home.vue
<template>
<div class="phoneContant">
<van-button type="warning" @click="goToNext">进入下一页</van-button>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
msg: "我是首页",
};
},
methods: {
goToNext() {
this.$router.push("/second");
},
},
};
</script>
<style>
</style>
Second.vue
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default {
data(){
return{
msg:"第二页"
}
}
}
</script>
<style>
</style>
运行
命令行输入
npm run serve
没问题的话,就能运行起来了。如果想要中断运行,终端里边用ctrl+c快捷键
网络封装
对axios进行封装一下,方便使用。在src下新建utils文件夹,utils下新建request.js,
import axios from "axios";
import { Notify } from "vant";
import router from "@/router";
const baseURL =BaseUrl
const service = axios.create({
baseURL,
withCredentials: true,
timeout: 30000,
});
service.interceptors.request.use(
(config) => {
const Nonce =
Math.ceil(+new Date() / 1000) + "" + Math.ceil(Math.random() * 10000);
const CurTime = Math.floor(+new Date() / 1000).toString();
config.headers["Content-Type"] = "application/json;charset=UTF-8";
return config;
},
(error) => {
return Promise.reject(error);
}
);
service.interceptors.response.use(
(response) => {
const res = JSON.parse(CryptoJS.decrypt(response.data));
if (!res.result) {
Notify({ type: "danger", message: res.message || "error" });
return Promise.reject(res.message || "error");
} else {
return res;
}
},
(error) => {
Notify({ type: "danger", message: error.message || "error" });
return Promise.reject(error);
}
);
export default service;
结语
现在只是搭建了工程,如果没有缺少步骤的话,应该是可以运行起来的,剩下的还有很多工作要做。。。
|