技术选型
公司现在需要开发移动端的h5,使用现在比较流行的vue 2.0开发,使用的脚手架是Vant2,网络访问使用的是axios,路由跳转使用的是vue-router,开发工具是vscode,
vue cli
vue
vuex
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


创建脚手架项目

vue create first-vue
选择vue 2

创建完成以后,会是这个样子

记住,后边要cd到工程里,否则还是在工程外创建引用之类的
下边用同样的方法,引入axios,router,还有vant需要使用的 postcss-px-to-viewport,postcss-pxtorem,lib-flexible

npm install vue-router@3.0.7
npm install axios
npm install vuex
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,内容

// Color Palette
@black: #000;
@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;
@red: #ee0a24;
@blue: #1989fa;
@orange: #ff976a;
@orange-dark: #ed6a0c;
@orange-light: #fffbe8;
@green: #07c160;// Gradient Colors
@gradient-red: linear-gradient(to right, #ff6034, #ee0a24);
@gradient-orange: linear-gradient(to right, #ffd01e, #ff8917);// Component Colors
@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
@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
@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
@animation-duration-base: 0.3s;
@animation-duration-fast: 0.2s;
@animation-timing-function-enter: ease-out;
@animation-timing-function-leave: ease-in;// Border
@border-color: @gray-3;
@border-width-base: 1px;
@border-radius-sm: 2px;
@border-radius-md: 4px;
@border-radius-lg: 8px;
@border-radius-max: 999px;

同样目录下,创建一个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里进行配置
访问资源路径,有个快捷方法,设置一个符号,用来直接指定到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");
// const CompressionWebpackPlugin = require("compression-webpack-plugin");
// // 定义压缩文件类型
// const productionGzipExtensions = ["js", "css"];
// let timeStamp = new Date().getTime();function resolve(dir) {return path.join(__dirname, dir);
}
module.exports = {// 基本路径publicPath: "./",// 输出文件目录 不写则默认根目录outputDir: "dist",assetsDir: "static", // 静态资源目录 (js, css, img, fonts)lintOnSave: false,// eslint-loader 是否在保存的时候检查// lintOnSave: 'error',// devServer: {//   // development server port 8000//   port: 8000,//   // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11//   proxy: {//     '/api/': {//       target: process.env.VUE_APP_APIUrl,//       changeOrigin: true//     }//   }// },// /assets/style/public.css.lesscss: {loaderOptions: {less: {lessOptions: {modifyVars: {// 或者可以通过 less 文件覆盖(文件路径为绝对路径)hack: `true; @import "@/assets/style/theme.less";`,},},},},},devServer: {// 设置主机地址// 设置默认端口port: 8080,// // 设置代理// proxy: {//   "/": {//     // target: "http://198.166.21.56:8080/",//     ws: true, // 支持ws协议;websocket的缩写;//     changeOrigin: true, // 是否跨域//     pathRewrite: {//       // 路径替换//       "^/api": "",//     },//   },// },},// use the full build with in-browser compiler?// https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only// compiler: false,// webpack配置// see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md   webpack链接API,用于生成和修改webapck配置//部署打包html带引号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.output.filename = `assets/js/[name].${timeStamp}.js`;// config.output.chunkFilename = `assets/js/[name].${timeStamp}.js`;config.plugins.push(new CompressionWebpackPlugin({algorithm: "gzip",test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),threshold: 10240,minRatio: 0.8,}));}config.externals = {//   'vue': 'Vue',//   'vuex': 'Vuex',//   'vue-router': 'VueRouter',//   'element-ui': 'ELEMENT',//   'Axios': 'axios',//   'jquery': '$',//   'moment': 'moment',//   'js-cookie': 'Cookies',//   'echarts': 'echarts',//   'tinymce/tinymce': 'tinymce'};// }},// configureWebpack: (config) => {// webpack配置,值位对象时会合并配置,为方法时会改写配置//   if (debug) { // 开发环境配置//     config.devtool = 'cheap-module-eval-source-map'//   } else { // 生产环境配置//   }//   Object.assign(config, { // 开发生产共同配置//     resolve: {//       alias: {//         '@': path.resolve(__dirname, './src')//设置路径别名//         //...//       }//     }//   })// },// vue-loader 配置项// https://vue-loader.vuejs.org/en/options.html// vueLoader: {},// 生产环境是否生成 sourceMap 文件productionSourceMap: false,// css相关配置 配置高于chainWebpack中关于css loader的配置// css: {//   // 是否使用css分离插件 ExtractTextPlugin//   extract: true,//   // 开启 CSS source maps?是否在构建样式地图,false将提高构建速度//   sourceMap: false,//   // css预设器配置项//   loaderOptions: {},//   // 启用 CSS modules for all css / pre-processor files.//   modules: false// },// use thread-loader for babel & TS in production build// enabled by default if the machine has more than 1 cores 构建时开启多进程处理babel编译//parallel: require('os').cpus().length > 1,// 是否启用dll// See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#dll-mode// dll: false,// PWA 插件相关配置// see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa//pwa: {},// webpack-dev-server 相关配置// devServer: {//   open: process.platform === 'darwin',//   host: '0.0.0.0',//   port: 8080,//   https: false,//   hotOnly: false,//   proxy: null, // 设置代理//   before: app => { }// },// 第三方插件配置pluginOptions: {// ...},
};

lintOnSave: false,这个的意思就是关闭语法检查,要不然会很多报错,运行不起来
在first-vue目录下,新建一个.postcssrc.js,在里边配置postcss

module.exports = {plugins: {//...autoprefixer: {browsers: ["Android >= 4.0", "iOS >= 7"],},"postcss-pxtorem": {rootValue: 37.5, //vant-UI的官方根字体大小是37.5propList: ["*"],},},
};

底部安全区适配
在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" /><metaname="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: '/dashboard/workplace',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,},
];

src目录下,新建store目录,下边新建index.js,对vuex进行配置

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const state = {openId:'',userStat:'0',identification:'',userInfo:{},active:'1',
}
const mutations = {setOpenid(state,payload){state.openId = payloadsessionStorage.setItem("openId", payload);},setUserStat(state,payload){state.userStat = payloadsessionStorage.setItem("userStat", payload);},setNumber(state,index) {state.active = index;}
}const action = {}
export default new Vuex.Store({state,mutations,action,
})

对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-barclass="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/), //判断是否为IOS
};export default {name: "Headers",//import引入的组件需要注入到对象中才能使用components: {},data() {//这里存放数据return {title: "",};},//监听属性 类似于data概念computed: {},//监控data中的数据变化watch: {$route: {handler(newRouter, fromRouter) {},immediate: true,},},//方法集合methods: {back() {this.$router.go(-1);return false;},},//生命周期 - 创建完成(可以访问当前this实例)created() {let cont = window.history.length;console.log("window.history.length-----------------roomstep");console.log(cont);},//生命周期 - 挂载完成(可以访问DOM元素)mounted() {},beforeCreate() {}, //生命周期 - 创建之前beforeMount() {}, //生命周期 - 挂载之前beforeUpdate() {}, //生命周期 - 更新之前updated() {}, //生命周期 - 更新之后beforeDestroy() {}, //生命周期 - 销毁之前destroyed() {}, //生命周期 - 销毁完成activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
};
</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 store from './store'
import Vuex from 'vuex'
import "vant/lib/index.less";
import "@/assets/style/public.css";
Vue.config.productionTip = false
import {GET,GETRESET,POST,PUT,DELETE,POSTJSON,PUTJSON
} from './service/index'
Vue.prototype.$http = {GET,GETRESET,POST,PUT,DELETE,POSTJSON,PUTJSON
};
Vue.use(Vant);
Vue.use(Vuex);
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

网络封装

对axios进行封装一下,方便使用。在src下新建service文件夹,utils下新建index.js

import axios from "axios";
import { Notify } from "vant";
import QS from 'qs'
import router from "@/router";const baseURL =BaseUrl// process.env.NODE_ENV === "development" ? "/api" : window.productionUrl;
//创建axios实例
const service = axios.create({baseURL, // api的base_url  window.productionUrlwithCredentials: 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));// 错误的status情况// console.log(res);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);}
);
/*** get方法,对应get请求GET * @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/
export function GET(url, params) {url = serviceAdapter(url);return new Promise((resolve, reject) => {axios.get(url, {params: params,paramsSerializer: function (params) {return QS.stringify(params, {arrayFormat: 'repeat'})}}, ).then(res => {// console.log(res)// if (!res.data && typeof (res.data) != "undefined") {//     res.data.data.rows = []// }// if (!res.data.data && typeof (res.data.data) != "undefined" && res.data.data != 0) {//     res.data.data = []// }resolve(res);}).catch(err => {reject(err)})});
}
export function GETRESET(url, params) {url = serviceAdapter(url);return new Promise((resolve, reject) => {axios.get(url, {params: params,paramsSerializer: function (params) {return QS.stringify(params, {arrayFormat: 'repeat'})}}, ).then(res => {// if (res.data.data === null) {//     res.data.data = " "; //返回值是null的// }// if (!res.data.data.rows && typeof (res.data.data.rows) != "undefined" && res.data.data.rows != 0) {//     res.data.data.rows = []// }// if (!res.data.data && typeof (res.data.data) != "undefined" && res.data.data != 0) {//     res.data.data = []// }resolve(res);}).catch(err => {reject(err)})})
}/*** post方法,对应post请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/
export function POST(url, params) {url = serviceAdapter(url);return new Promise((resolve, reject) => {axios.post(url, QS.stringify(params, {arrayFormat: 'repeat'})).then(res => {resolve(res);}).catch(err => {reject(err)})});
}/*** postJson方法,对应post请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/
export function POSTJSON(url, params) {url = serviceAdapter(url);return new Promise((resolve, reject) => {axios.post(url, params).then(res => {resolve(res);}).catch(err => {reject(err)})});
}/*** put方法,对应put请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/
export function PUT(url, params) {url = serviceAdapter(url);return new Promise((resolve, reject) => {axios.put(url, QS.stringify(params, {arrayFormat: 'repeat'})).then(res => {resolve(res);}).catch(err => {reject(err)})});
}/*** PUTJSON方法,对应put请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/
export function PUTJSON(url, params) {url = serviceAdapter(url);return new Promise((resolve, reject) => {axios.put(url, params).then(res => {resolve(res);}).catch(err => {reject(err)})});
}/*** delete方法,对应delete请求* @param {String} url [请求的url地址]* @param {Object} params [请求时携带的参数]*/
export function DELETE(url, params) {url = serviceAdapter(url);return new Promise((resolve, reject) => {axios.delete(url, {params: params,paramsSerializer: params => {return QS.stringify(params, {indices: false})}}).then(res => {resolve(res);}).catch(err => {reject(err)})});
}
export default service;

结语

现在只是搭建了工程,如果没有缺少步骤的话,应该是可以运行起来的,剩下的还有很多工作要做。。。

补充

是因为版本问题,是你安装了最新的vuex 4 以上导致:
解决办法:安装3系列的:
先卸载 安装的 4 版本的vuex
npm uninstall vuex
安装 3.6.2版本的
npm install --save vuex@3.6.2

创建基于vue的H5相关推荐

  1. vue 微信公众号支付接口_基于vue的h5项目之支付宝支付与微信支付

    本文仅记录基于vue开发h5项目过程中使用支付宝和微信支付过程中的重点与槽点,仅为前端部分,如有疏漏不正之处,请于文末评论探讨.注意:标红部分灰常重要,仔细阅读官方文档非常重要,耐心非常重要,细心非常 ...

  2. html5快速开发模板生成器,推荐一个基于Vue 的 H5 快速开发模板

    本项目以基于 vue-cli4 和 Vant-ui 搭建的,进行移动端开发中的一些最佳实践方案 模板地址 动动你的小手点颗star 样式适配 在移动端网页开发时,样式适配始终是一个绕不开的问题.对此目 ...

  3. vue lang_推荐一个基于Vue 的 H5 快速开发模板

    关注 Vue社区,回复"加群" 加入我们一起学习,天天进步 praise juejin.im/post/5e612534e51d4527017971a2 模板基于 vue-cli4 ...

  4. 基于vue 的h5微信分享

    之前一直都是使用的html,jquery,js等做的微信分享,现在项目都改用vue做了,但是微信分享还是要接入的,这里简单分享一下移动端vue如何接入微信分享. 1.首先安装微信分享依赖 npm in ...

  5. linux 使用ssr客户端_【第一期】基于 @vue/cli3 与 koa 创建 ssr 工程

    什么是基于同构代码的 SSR 服务(Server-side rendering based on isomorphic code) 首先,我们需要先明白什么是 spa (single page app ...

  6. Vue-app之H5基于Vue初始化一个移动端项目H5APP

    Web App,顾名思义是指基于Web的应用,基本采用Html5语言写出,不需要下载安装.类似于现在所说的轻应用.基于浏览器运行的应用,基本上可以说是触屏版的网页应用. 一个web app如何拔地而起 ...

  7. 音乐、视频播放模式切换实现方案及原理解析(基于vue、vuex、h5 audio)

    音乐.视频播放模式切换实现方案及原理解析(基于vue.vuex.h5 audio) 播放模式有三种: 顺序播放 随机播放 单曲循环 定义为一个playMode对象并向外暴露,内含三种播放模式,即为: ...

  8. 创建基于webpack打包的vue项目

    创建基于webpack打包的vue项目 结合win7.element-ui.vue(vue-router.vue-cli).webpack等技术,完成了项目的基础工作.难则不会,会则不难:贵在经验总结 ...

  9. vue.js毕业设计,基于vue.js前后端分离教室预约系统(H5移动项目) 开题报告

      毕业论文 基于Vue.js的教室预约系统(H5) 开题报告 学    院: 专    业: 年    级: 学生姓名: 指导教师: 黄菊华   XXXX大学本科生毕业论文(设计)开题报告书 姓   ...

最新文章

  1. 12岁AI开发者现身DuerOS发布会:得开发者得天下
  2. Android基础--tools:context=.TestActivity作用
  3. shiro之AuthenticationStrategy
  4. Chinese savior crepe
  5. ajax获取后台数据出错parsererror
  6. 设计师应该尊重技术的限制
  7. matlab butter 低通,matlab butter 用法
  8. 我用 Python 抓取了 7000 多本电子书
  9. Listary一款不只是程序员需要的软件
  10. Ragel State Machine Compiler 的速度测试
  11. 油田智能化远程监控系统_油气田长停井图像远程传输监控系统
  12. QT——连接腾讯云物联网平台
  13. Revit出图问题:打印机中新建纸张尺寸?批量导出图纸?
  14. osgEarth示例分析——osgearth_graticule
  15. Win10系统程序以管理员身份开机自启动配置
  16. 什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC?
  17. am335x uboot启动流程分析
  18. 驴途网--技术小结1
  19. Android开发之漫漫长途 XIX—HTTP
  20. J2SE简单的数据库连接池

热门文章

  1. 分享一个挺不错的Git视频教程
  2. 3年功能测试经验,面试想拿到15k很难吗?
  3. LED电子显示屏真彩显示的几种关键技术[转]
  4. Mybatis深层理解之mybatis到底为我们做了什么?
  5. winscp开启ftp_Linux 之WinSCP连接FTP
  6. 开箱即用的后台UI框架eui(原eadmin)
  7. 金典《歌手》2019即将首播 创作季上演神仙打架
  8. 嘘...偷偷教你破解“朋友圈三天可见”
  9. 有一种爱,我们不能称之为爱情
  10. 相濡以沫,何能相忘于江湖