【Vue2项目(尚品汇前台)】(七)Pay支付、Person个人中心模块搭建

本文主要是介绍【Vue2项目(尚品汇前台)】(七)Pay支付、Person个人中心模块搭建,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、导航守卫

全局守卫:前置守卫(在路由跳转之间进行判断) to:可以获取到你要跳转到哪个路由信息 from:可以获取到你从哪个路由而来的信息
next:放行函数 next()放行 next(path)放行到指定路由

放行的条件首先是要看登没登陆,所以要先识别token
从store获取token,在router.js文件中引入

import store from "@/store";//全局守卫:前置守卫(在路由跳转之间进行判断)
router.beforeEach(async(to, from, next) => {// to and from are both route objects. must call `next`.//获取仓库中的token-----可以确定用户是登录了let token = store.state.user.token;let name = store.state.user.userInfo.name;//用户登录了if (token) {//已经登录而且还想去登录------不行if (to.path == "/login" || to.path == "/register") {next("/home");} else {//已经登陆了,访问的是非登录与注册//登录了且拥有用户信息放行if (name) {next();} else {//登陆了且没有用户信息//在路由跳转之前获取用户信息且放行try {//获取用户信息await store.dispatch("getUserInfo");next();} catch (error) {//token失效从新登录//清除tokenawait store.dispatch("logout");// 回到登录页this.$router.push("/login");}}}} else {//未登录:不能去交易相关、不能去支付相关【pay|paysuccess】、不能去个人中心//未登录去上面这些路由-----登录let toPath = to.path;if (toPath.includes("/trade") || toPath.includes("/pay") || toPath.includes("/center")) {//把未登录的时候向去而没有去成的信息,存储于地址栏中【路由】next("/login?redirect=" + toPath);// console.log(toPath);} else {//去的不是上面这些路由(home|search|shopCart)---放行next();}}
});

守卫的多种情况:
已经登录了:

  1. 已经登录了还想转跳到登录(不能放行)
  2. 已经登录了还想转跳到非登录和注册(不能放行)
  3. 登录了且拥有用户信息(放行)
  4. 登录了但是没有用户信息,进行判断,获取到了用户信息(放行),没获取到(放回到登录页)

未登录:

  1. 不能去交易支付等页面,还有个人中心
  2. 把未登录的时候向去而没有去成的信息,存储于地址栏中【路由】next("/login?redirect=" + toPath);,这一点很妙,多看看

二、交易页面的静态导入

这里很简单,就跳过了

给购物车里的结算添加转跳

<div class="sumbtn"><router-link class="sum-btn" to="/trade">结算</router-link>
</div>

三、获取、渲染交易页数据

1. 写api

//获取用户地址信息
//URL:/api/user/userAddress/auth/findUserAddressList  method:get
export const reqAddressInfo = () =>requests({url: "/user/userAddress/auth/findUserAddressList/",method: "get"});
//获取商品清单
//URL:/api/order/auth/trade   method:get
export const reqOrderInfo = () =>requests({url: "/order/auth/trade",method: "get"});

2. 写仓库Trade.js

import { reqAddressInfo, reqOrderInfo } from "@/api";const actions = {//获取用户地址信息async getUserAddress({ commit }) {let result = await reqAddressInfo();// console.log(result);if (result.code == 200) {commit("GETUSERADDRESS", result.data);}},//获取商品清单数据async getOrderInfo({ commit }) {let result = await reqOrderInfo();if (result.code == 200) {commit("GETORDERINFO", result.data);}},
};
const mutations = {GETUSERADDRESS(state, address) {state.address = address;},GETORDERINFO(state, orderInfo) {state.orderInfo = orderInfo;},
};
const state = {address: [],orderInfo: {},
};
const getters = {};
export default {actions,mutations,state,getters,
};

3. 在支付Trade.html页面派发action

mounted() {this.$store.dispatch("getUserAddress");this.$store.dispatch("getOrderInfo");},

4. 渲染数据

拿数据

  computed: {...mapState({addressInfo: (state) => state.trade.address,orderInfo: (state) => state.trade.orderInfo,}),

放动态数据
在这里插入图片描述
利用排他思想来写默认地址

//修改默认地址changeDefault(address, addressInfo) {addressInfo.forEach((item) => {//全部的为0item.isDefault = 0;});address.isDefault = 1; //点击的为1},

动态拿到选中的默认地址,然后渲染到提交订单上面的地址栏

将来提交订单最终选中地址userDefaultAddress() {//find:查找数组当中符合条件的元素返回,最为最终结果return this.addressInfo.find((item) => item.isDefault == 1) || {};},

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

5. 用户留言

data() {return {msg: "", //收集买家的留言信息orderId: "", //订单号};},

写一个msg来存用户的留言,用v-model来绑定

<div class="bbs"><h5>买家留言:</h5><textarea placeholder="建议留言前先与商家沟通确认" class="remarks-cont" v-model="msg" ></textarea>
</div>

四、提交订单

1. 导入静态组件

2. 配路由

path: "/pay",
component: () =>import ("@/pagaes/Pay"),meta: {show: true,},

3.提交订单分析

当你点击提交订单,应该告知服务器是谁买了,还有地址、电话、支付、金额、产品
在点击提交订单的按钮时,还需要向服务器发起一次请求【告知上面的信息】

4.写提交订单api

//提交订单的接口
//URL:/api/order/auth/submitOrder?tradeNo={tradeNo}  method:post
export const reqSubmitOrder = (tradeNo, data) =>requests({url: `/order/auth/submitOrder?tradeNo=${tradeNo}`,data,method: "post"});

在这就没用到vuex把信息存入仓库了,但是要怎么拿到api呢
在文件里引入

import { reqSubmitOrder } from "@/api";

但是这种方法只能用在一个文件,要是要引用多个,要写非常多个api引入,非常不模块化
这时候可以在main.js里统一接口api

//统一接口api文件夹里面全部请求函数
//统一引入
import * as API from "@/api";

在这里插入图片描述
这样就只用在文件里引用一次,就可以全部api了

5.拿数据

//提交订单async submitOrder() {//交易编码let { tradeNo } = this.orderInfo;//其余的六个参数let data = {consignee: this.userDefaultAddress.consignee, //最终收件人的名字consigneeTel: this.userDefaultAddress.phoneNum, //最终收件人的手机号deliveryAddress: this.userDefaultAddress.fullAddress, //收件人的地址paymentWay: "ONLINE", //支付方式orderComment: this.msg, //买家的留言信息orderDetailList: this.orderInfo.detailArrayList, //商品清单};//需要带参数的:tradeNolet result = await this.$API.reqSubmitOrder(tradeNo, data);// console.log(result);if (result.code == 200) {(this.orderId = result.data),//路由跳转 + 路由传递参数this.$router.push("/pay?orderId=" + this.orderId);} else {alert(result.data);}},

五、获取订单支付信息

//获取支付信息
//URL:/api/payment/weixin/createNative/{orderId}  GET
export const reqPayInfo = (orderId) =>requests({url: `/payment/weixin/createNative/${orderId}`,method: "get"});
//工作的时候:尽量别再生命周期函数中async|awaitmounted() {this.getPayInfo();},methods: {async getPayInfo() {let result = await this.$API.reqPayInfo(this.orderId);// console.log(result);//如果成功:组件当中存储支付信息if (result.code == 200) {this.payInfo = result.data;} else {alert(result.data);}},
}

六、微信支付

1. 引入ElementUI组件

import { Button, MessageBox } from "element-ui";
Vue.component(Button.name, Button);
//ElementUI注册组件的时候,还有一种写法,挂在原型上
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;

2. 使用弹框组件

open() {this.$alert(`<img src=${url} />`, "请你微信支付", {dangerouslyUseHTMLString: true,//中间布局center: true,//是否显示取消按钮showCancelButton: true,//取消按钮的文本内容cancelButtonText: "支付遇见问题",//确定按钮的文本confirmButtonText: "已支付成功",//右上角的叉子没了showClose: false,
}

3.使用QRCODE

安装脚手架 npm i qrcode

//生成二维(地址)let url = await QRCode.toDataURL(this.payInfo.codeUrl);

用模板字符串写入返回的二维码

//获取支付订单状态
//URL:/api/payment/weixin/queryPayStatus/{orderId}  get
export const reqPayStatus = (orderId) =>requests({url: `/payment/weixin/queryPayStatus/${orderId}`,method: 'get'});

设置一个长询问定时器,每隔一秒查看用户是否支付

async getPayInfo() {let result = await this.$API.reqPayInfo(this.orderId);// console.log(result);//如果成功:组件当中存储支付信息if (result.code == 200) {this.payInfo = result.data;} else {alert(result.data);}},async open() {//生成二维(地址)let url = await QRCode.toDataURL(this.payInfo.codeUrl);this.$alert(`<img src=${url} />`, "请你微信支付", {dangerouslyUseHTMLString: true,//中间布局center: true,//是否显示取消按钮showCancelButton: true,//取消按钮的文本内容cancelButtonText: "支付遇见问题",//确定按钮的文本confirmButtonText: "已支付成功",//右上角的叉子没了showClose: false,//关闭弹出框的配置值beforeClose: (type, instance, done) => {//type:区分取消|确定按钮//instance:当前组件实例//done:关闭弹出框的方法if (type == "cancel") {//点击支付遇到问题alert("请联系管理员");//清除定时器clearInterval(this.timer);this.timer = null;//关闭弹出框done();} else {// 点击支付成功//判断是否真的支付了//开发人员:为了自己方便,这里判断先不要了// if (this.code == 200) {//清除定时器clearInterval(this.timer);this.timer = null;//关闭弹出框done();//跳转到下一路由this.$router.push("/paysuccess");}},});//你需要知道支付成功|失败//支付成功,路由的跳转,如果支付失败,提示信息//定时器没有,开启一个新的定时器if (!this.timer) {this.timer = setInterval(async () => {let result = await this.$API.reqPayStatus(this.orderId);// console.log(result);if (result.code == 200) {//第一步:清除定时器clearInterval(this.timer);this.timer = null;//保存支付成功返回的codethis.code = result.data;//关闭弹出框this.$msgbox.close();//跳转到下一路由this.$router.push("/paysuccess");} else {console.log('未支付直接跳转了');}}, 1000);}},

这里设置200是因为防止用户未支付就点击已支付成功

beforeClose: (type, instance, done)
type:区分取消|确定按钮
instance:当前组件实例
done:关闭弹出框的方法

七、个人中心

1. 二级路由的创建

在这里插入图片描述
当有一种页面是有分侧边栏和主页面,切换不同页面时,可以使用二级路由导航
在侧边栏的文件夹里再分出来内容这一栏的小组件
在这里插入图片描述
声明式导航

在这里插入图片描述
还要设置路由组件出口
在这里插入图片描述
都设置完了会发现,当我们点击进来的时候,只有侧边栏,内容部分缺失,这时候需要重定向路由,让你你点进去页面,先显示主页面

{ //重定向一上来就展示myorder组件path: '',redirect: 'myorder'}

2. 获取数据、展示数据

//获取个人中心的数据
//api/order/auth/{page}/{limit}  get 
export const reqMyOrderList = (page, limit)  =>requests({url: `/order/auth/${page}/${limit}`,method: 'get'});
data() {return {//初始化参数//当前第几页page: 1,//每一页展示数据个数limit: 3,//存储我的订单的数据myOrder: {},};},mounted() {//获取我的订单的数据方法this.getData();},methods: {//获取我的订单的方法async getData() {//解构出参数const { page, limit } = this;let result = await this.$API.reqMyOrderList(page, limit);if (result.code == 200) {this.myOrder = result.data;}},//获取当前点击那一页getPageNo(page){//修改组件响应式数据pagethis.page = page;this.getData();}},

渲染数据
在这里插入图片描述
当三个都是一样的时候,评论晒单只要一个,只要第一个数据,后面的都不要
v-if="index == 0"

3. 分页器

<Pagination:pageNo="page":pageSize="limit":total="myOrder.total":continues="5"@getPageNo="getPageNo"
/>
methods: {//获取我的订单的方法async getData() {//解构出参数const { page, limit } = this;let result = await this.$API.reqMyOrderList(page, limit);if (result.code == 200) {this.myOrder = result.data;}},//获取当前点击那一页getPageNo(page){//修改组件响应式数据pagethis.page = page;this.getData();}},

八、路由独享与组件内守卫

1. 路由独享守卫

想一想有一种情况,当用户登陆之后,他直接在地址栏输入到支付界面,这肯定是不行的,那要怎么实现当用户登录之后,也只能通过正常的点击商品购买才能到支付界面和支付成功界面

{path: "/trade",component: () =>import("@/pagaes/Trade"),meta: {show: true,},// 路由独享守卫beforeEnter: (to, from, next) => {if (from.path == '/shopcart') {next()} else {next(false)}}
},

next(false)意思为:从哪来,回哪去

支付页面也要设置

{path: "/pay",component: () =>import("@/pagaes/Pay"),meta: {show: true,},// 路由独享守卫beforeEnter: (to, from, next) => {if (from.path == '/trade') {next()} else {next(false)}}
},

2. 组件内守卫

也可以直接写在组件里

beforeRouteEnter(to, from, next) {// 在渲染该组件的对应路由被 confirm 前调用// 不!能!获取组件实例 `this`// 因为当守卫执行前,组件实例还没被创建if (from.path == "/pay") {next();} else {next(false);}},beforeRouteUpdate(to, from, next) {// 在当前路由改变,但是该组件被复用时调用// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。// 可以访问组件实例 `this`console.log("12313131311313");},beforeRouteLeave(to, from, next) {// 导航离开该组件的对应路由时调用// 可以访问组件实例 `this`next();},

九、图片懒加载

类似于大型的淘宝商城、京东等网页,设计大量的商品图片信息,如果我们使页面包含的所有图片一次性加载完成,那用户体验很差。
目前流行的做法是滚动动态加载,也就是懒加载,显示在屏幕之外的图片默认不加载,随着页面的滚动,图片进入了显示的范围,则触发图片的加载显示
这样做的好处,一是页面加载速度快(浏览器进度条和加载转圈很快就结束了,这样用户的体验也比较好),而是节省流量,因为不可能每一个用户会把页面从上到下滚动完

npm i vue-lazyload

引入插件

import VueLazyload from 'vue-lazyload'

安装插件

// or with options
const loadimage = require('./assets/loading.gif')
const errorimage = require('./assets/error.gif')

配置对象

Vue.use(VueLazyload, {preLoad: 1.3,error: errorimage,loading: loadimage,attempt: 1
})

加入自定义指令

<ul><li v-for="img in list"><img v-lazy="img.src" ></li>
</ul>

十、路由懒加载

当打包构建应用时,javascript包会变得非常大,影响页面加载
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了

例子

{path: "/paySuccess",component: () =>import("@/pagaes/PaySuccess"),meta: {show: true,},
},

十一、vee-validate表单验证插件

npm i vee-validate

引入

import Vue from 'vue';
import VeeValidate from 'vee-validate';

使用

Vue.vue(VeeValidate)

在入口文件引一次插件

import ‘@/plugins/validate’;

表单验证

//表单验证
VeeValidate.Validator.localize("zh_CN", {messages: {...zh_CN.messages,is: (field) => `${field}必须与密码相同`, // 修改内置规则的 message,让确认密码和密码相同},attributes: {phone: "手机号",code: "验证码",password: "密码",password1: "确认密码",agree:'协议'},
});

自定义校验规则

//自定义校验规则
VeeValidate.Validator.extend("tongyi", {validate: (value) => {return value;},getMessage: (field) => field + "必须同意",
});

使用

<div class="content"><label>手机号:</label><inputplaceholder="请输入你的手机号"v-model="phone"name="phone"v-validate="{ required: true, regex: /^1\d{10}$/ }":class="{ invalid: errors.has('phone') }"/><span class="error-msg">{{ errors.first("phone") }}</span></div>

能确定你是否全部验证成功,返回值是布尔值

const success = await this.$validator.validateAll();

这篇关于【Vue2项目(尚品汇前台)】(七)Pay支付、Person个人中心模块搭建的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/matmacchiato/article/details/128755690
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/277059

相关文章

Maven项目中集成数据库文档生成工具的操作步骤

《Maven项目中集成数据库文档生成工具的操作步骤》在Maven项目中,可以通过集成数据库文档生成工具来自动生成数据库文档,本文为大家整理了使用screw-maven-plugin(推荐)的完... 目录1. 添加插件配置到 pom.XML2. 配置数据库信息3. 执行生成命令4. 高级配置选项5. 注意事

eclipse如何运行springboot项目

《eclipse如何运行springboot项目》:本文主要介绍eclipse如何运行springboot项目问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目js录当在eclipse启动spring boot项目时出现问题解决办法1.通过cmd命令行2.在ecl

SpringCloud使用Nacos 配置中心实现配置自动刷新功能使用

《SpringCloud使用Nacos配置中心实现配置自动刷新功能使用》SpringCloud项目中使用Nacos作为配置中心可以方便开发及运维人员随时查看配置信息,及配置共享,并且Nacos支持配... 目录前言一、Nacos中集中配置方式?二、使用步骤1.使用$Value 注解2.使用@Configur

Windows Server 2025 搭建NPS-Radius服务器的步骤

《WindowsServer2025搭建NPS-Radius服务器的步骤》本文主要介绍了通过微软的NPS角色实现一个Radius服务器,身份验证和证书使用微软ADCS、ADDS,具有一定的参考价... 目录简介示意图什么是 802.1X?核心作用802.1X的组成角色工作流程简述802.1X常见应用802.

SpringBoot项目Web拦截器使用的多种方式

《SpringBoot项目Web拦截器使用的多种方式》在SpringBoot应用中,Web拦截器(Interceptor)是一种用于在请求处理的不同阶段执行自定义逻辑的机制,下面给大家介绍Sprin... 目录一、实现 HandlerInterceptor 接口1、创建HandlerInterceptor实

Maven项目打包时添加本地Jar包的操作步骤

《Maven项目打包时添加本地Jar包的操作步骤》在Maven项目开发中,我们经常会遇到需要引入本地Jar包的场景,比如使用未发布到中央仓库的第三方库或者处理版本冲突的依赖项,本文将详细介绍如何通过M... 目录一、适用场景说明​二、核心操作命令​1. 命令格式解析​2. 实战案例演示​三、项目配置步骤​1

使用Python和Tkinter实现html标签去除工具

《使用Python和Tkinter实现html标签去除工具》本文介绍用Python和Tkinter开发的HTML标签去除工具,支持去除HTML标签、转义实体并输出纯文本,提供图形界面操作及复制功能,需... 目录html 标签去除工具功能介绍创作过程1. 技术选型2. 核心实现逻辑3. 用户体验增强如何运行

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

Spring 缓存在项目中的使用详解

《Spring缓存在项目中的使用详解》Spring缓存机制,Cache接口为缓存的组件规范定义,包扩缓存的各种操作(添加缓存、删除缓存、修改缓存等),本文给大家介绍Spring缓存在项目中的使用... 目录1.Spring 缓存机制介绍2.Spring 缓存用到的概念Ⅰ.两个接口Ⅱ.三个注解(方法层次)Ⅲ.

一文教你Java如何快速构建项目骨架

《一文教你Java如何快速构建项目骨架》在Java项目开发过程中,构建项目骨架是一项繁琐但又基础重要的工作,Java领域有许多代码生成工具可以帮助我们快速完成这一任务,下面就跟随小编一起来了解下... 目录一、代码生成工具概述常用 Java 代码生成工具简介代码生成工具的优势二、使用 MyBATis Gen