基于vue3.0+vantUI+sass实现的移动端商城

基于yg_mobile开发的一款简单的h5商城页面

yg_mobile 自开发vue移动端的启动项目源码
yg_mobile项目的gitee地址:https://gitee.com/yango520/yg_mobile

yg_mobile方便往后自己开发vue移动端项目时候,不需要再做其他配置和造轮子等复杂工作

特别声明:UI是参考yoyo的设计,仅用于学习,非商业用途


项目gitee地址:https://gitee.com/yango520/yg_shop

YG商城预览地址: 传送门

查看预览图

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述

项目创建环境:

  • vue:v3.10.0
  • node:v10.11.0
  • npm: 6.14.8

项目创建过程:(阐述)

vue create yg_mobile

  1. Manually select featues 选择手动配置
  2. 选择所需要的依赖(按空格选择) Babel, Router, Vuex, CSS Pre-processors, Linter / Formatter
  3. Use history mode for router? 是否选择history模式(另外一个hash模式),这里选择是Y
  4. 选择预处理器,Sass/SCSS(with node-sass)
  5. 选择代码校验,ESLint+Prettier
  6. 选择校验时间,Lint on save, 保存就校验
  7. 选择配置文件,In package.json
  8. 最后是否选择以上配置为以后项目开发默认配置,这里可以选择否N

文档

1.需要安装的依赖

依赖库说明
Router路由配置
Vuex状态管理
SCSScss预处理
axios网络请求
postcss-px2rem移动端适配rem
lib-flexiblerem适配跟上面一起用
Vant移动端UI库:官网地址
fastclick处理移动端click事件300毫秒延迟

2. 创建配置vue配置文件

在根目录新建一个vue.config.js的文件,用来配置vue的各项配置内容

module.exports = {
}

3. 配置服务器/代理相关配置

在vue.config.js里面添加

/** 
 * 服务器代理 相关配置  
 * port:启动端口号
 * host:设置反问地址,默认'localhost','0.0.0.0'设置为允许ip访问
 * open:浏览器自启动
 * proxy:配置接口代理
 */
devServer: {
	port: 8085,
	host: '0.0.0.0',
	open: true,
	proxy: {
		'/apis': {
			target: '',
			  changeOrigin: true,
			  pathRewrite: {
			    '^/apis': '这里为接口api地址'
			  }
			}
		}
	}
}

4. 配置 postcss-px2rem 和 lib-flexible 移动端适配rem

在vue.config.js中配置

/* css转换设置 */
css: {
	loaderOptions: {
		css: {},
		postcss: {
			plugins: [
				require('postcss-px2rem')({
					remUnit: 37.5,  //这里将屏幕分为10分(10rem),也就是10*37.5=375px就等于屏幕100%,如果不需要被转化,在style中直接写PX大写
				})
			]
		}
	}
},

然后在main.js中注册引用

//移动端布局
import 'lib-flexible'

5. 全局引用vant UI库

在main.js中引入

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

6.处理移动端click事件300毫秒延迟问题

在main.js中引用

/* 300毫秒点击延迟问题的解决方案(尤其是移动端)优化用户体验 */
import fastClick from 'fastclick'
fastClick.attach(document.body)

7. 配置静态资源别名

在vue.config.js中配置。

Vue CLI 内部的 webpack 配置是通过 webpack-chain (链式操作)维护的。这个库提供了一个 webpack 原始配置的上层抽象,使其可以定义具名的 loader 规则和具名插件,并有机会在后期进入这些规则并对它们的选项进行修改。官网文档

//在输出外部
const path = require('path');
function resolve(dir) {
	return path.join(__dirname, dir)
}

//在export内部
chainWebpack: (config) => {
	//修改文件引入自定义路径
	config.resolve.alias
		.set('@', resolve('src'))
		.set('styles', resolve('src/styles'))
},

如需要在style引入styles里的scss文件,则 @import '~styles/theme'; ,注意如果在style中引入,需要在前面添加 ~ 符号。

8. 配置打包静态资源路径问题

在vue.config.js中配置

//打包配置,解决页面空白的配置方案。
	publicPath:process.env.NODE_ENV == "production" ? "./" : "/",  

9. 封装路由跳转

在src/router/index.js配置

  • this.isleftthis.isright 是配置跳转页面过渡动画
  • path为跳转地址
  • par为跳转需要的参数对象
  • 在页面js中调用 this.$router.togo(path: string, opt: object)
  • 在标签可以直接调用 $router.togo(path: string, opt: object)
  • 在页面获取页面传递过来的参数 this.$route.query
// 需要左方向动画的路由用this.$router.togo('****', opt)
VueRouter.prototype.togo = function (path, par) {
  this.isleft = true
  this.isright = false
  this.push({
    path: path,
    query: par
  })
}
// 跳转指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面),传参跟push一样
VueRouter.prototype.toReplace = function (path, par) {
  this.isleft = true
  this.isright = false
  this.replace({
    path: path,
    query: par
  })
}
// 需要返回按钮动画的路由用this.$router.goBack(),返回上一个路由
VueRouter.prototype.goBack = function (n) {
  this.isright = true
  this.isleft = false
  this.go(n || -1)
}
// 点击浏览器返回按钮执行,此时不需要路由回退
VueRouter.prototype.togoback = function () {
  this.isright = true
  this.isleft = false
}
// 点击浏览器前进按钮执行
VueRouter.prototype.togoin = function () {
  this.isright = false
  this.isleft = true
}

10. 配置页面跳转动画

  • 在src/routger/index.js路由跳转里配置动画方向 isrightisleft;
  • 在App.vue页面修改如下
<template>
  <div id="app">
    <transition :name="transitionName">
      <router-view class="Router"></router-view>
    </transition>
  </div>
</template>

<script>
export default {
  name: 'App',
  data () {
    return {
      transitionName: ''
    }
  },
  watch: {
    $route () {
      if (this.$router.isleft) {
        this.transitionName = 'slideleft'
      }
      if (this.$router.isright) {
        this.transitionName = 'slideright'
      }
    }
  },
  mounted () {
  }
}
</script>

<style lang="scss">
  $body-bg-color: #f0f0f0;
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #484848;
  }

  // 设置跳转页面过渡动画
  .Router {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    width: 100%;
    min-height: 100%;
    background-color: $body-bg-color;
    transition: all .3s ease;
    -moz-transition: all .3s ease;
    -webkit-transition: all .3s ease;
  }
  .slideleft-enter,
  .slideright-leave-active {
    opacity: 1;
    transform: translate3d(80% 0, 0);
    -webkit-transform: translate3d(80%, 0, 0);
    -moz-transform: translate3d(80%, 0, 0);
  }
  .slideleft-leave-active,
  .slideright-enter {
   opacity: 1;
   transform: translate3d(-80% 0, 0);
   -webkit-transform: translate3d(-80%, 0, 0);
   -moz-transform: translate3d(-80%, 0, 0);
  }
</style>

11. 封装网络请求,配置axios

在vue.config.js配置代理

'/api': {
	target: '',
		changeOrigin: true,
		pathRewrite: {
			'^/api': '这里为接口api地址'
		}
	}
}

在src里新建一个api文件夹,包含3个文件 api.js, configApi.js, index.js

api.js 用于存放api接口文档

const Api = {
	get_img: `/get_img`,
}

export default Api;

configApi.js 用去封装请求,拦截请求

/* eslint-disable */
import axios from 'axios'
import router from '@/router'
import { Toast } from 'vant'
import { Dialog } from 'vant'

/**
* 定义请求常量
* TIME_OUT、ERR_OK
*/

const TIME_OUT =38000;    // 请求超时时间
const API_HOST = '/apis'  

// 请求超时时间
axios.defaults.timeout = TIME_OUT

// 封装请求拦截
axios.interceptors.request.use(config => {
		// 发起请求,取消掉当当前正在进行的相同请求
		return config
	},
	error => {
		return Promise.reject(error)
	}
)
// 封装响应拦截,判断token是否过期
axios.interceptors.response.use(
  response => {
  	return response
  },
  error  => {
  	if (error.response) {
  		switch (error.response.status) {
  			case 400:
  				error.message = 'Status:400'
  				break;
  			case 401:
  				error.message = 'Status:401'
  				break;
  			case 403:
  				error.message = 'Status:403'
  				break;
  			case 404:
  				error.message = 'Status:404'
					// router.toReplace('/error/404', {err: '内容不存在或者已被删除'})
  				break;
  			case 405:
  				error.message = 'Status:405'
  				break;
  			case 408:
  				error.message = 'Status:408'
  				break;
  			case 500:
  				error.message = 'Error:500'
					// router.toReplace('/error/404', {err: '服务器出错咯!'})
  				break;
  			case 501:
  				error.message = 'Status:501'
  				break;
  			case 502:
  				error.message = 'Status:502'
  				break;
  			case 503:
  				error.message = 'Status:503'
  				break;
  			case 504:
  				error.message = 'Network Timeout 504'
  				break;
  			default:
  				error.message = `ERROR:${error.response.status}`
					break;
  		}
  	}
		else if(error.request){
			// 捕获超时请求
			error.message = 'TimeOut';
		}
		return Promise.reject(error);
  }
)
// 封装请求
export function Axios(requestUrl, params, type = 'POST') {
  return new Promise((resolve,reject) => {
    axios({
      url: API_HOST + requestUrl,
      method: type,
      data: params
    }).then(res => {
      resolve(res.data)
    }).catch(err => {
			Toast.clear()
			Dialog({
			  message: '网络开小差啦~',
			  closeOnClickOverlay: true
			})
      reject(err);
    })
  })
}

index.js 封装各个请求方法

import Api from '@/api/api'
import { Axios } from './configApi'

class Http {
	getImg(params){
		return Axios(Api.get_img, params);
	}
	ALL(url, params, type){
		return Axios(url, params, type);
	}
}

export default new Http();

12. 配置状态管理vuex

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值