尚品汇【注册与登录】

一、注册部分

1、v-model 双向绑定收集表单数据到data中

     (data===vc._data,最后会通过Object.defineProperty中的getter与setter,收集的数据会放到vc身上)

2、注册手机验证码接口/api/user/passport/sendCode/phone ,phone手机号码位必选项

(1)配置axios

//注册页面 验证码 /api/user/passport/sendCode/phone   这里需要传递一个参数phone手机号【验证后的】给服务器
export const reqSendCode=(phone)=>{
    //用户没有输入电话的情况,控制台会有错误
      return phone ? axs({method:'get',url:`/api3/user/passport/sendCode/${phone}`}) : '';//传递手机号 这里走的/api3代理

}

--配置引入的axios实例对象axs,使用模块化分别暴露,暴露函数(函数返回axios请求实例对象)

--这里我们url路径上使用的/api3,走的是'/api3'的代理,处理跨域问题。

--函数接收参数,并通过模板字符串写入url路径

(2)使用vuex对应组件小仓库

async getYanZhenCode({commit},phone){
        let response=await reqSendCode(phone);//传递参数【手机号】
        if(response.code===200){
            commit('GETYANZHENCODE',response.data);//成功就联系mutations把服务器返回的验证码传递过去
            return 'ok';//调用函数返回一个成功的promise对象,告诉对应调用此函数的dispatch【的组件】,我注册成功了
        }
        else{
            return Promise.reject(new Error('err'));//返回一个失败的promise对象
        }
    }

--导入请求函数reqSendCode,actions对象中配置async函数使用await等待请求出结果并拿到服务器返回的整个数据对象,调用reqSendCode函数发起请求返回一个带有状态 带有数据的promise对象【成功或失败】

--await等待请求出结果以后,根据服务器返回的状态code返回相应的状态的promise对象,失败会抛出错误【调用此async函数时返回】

--async函数返回一个普通的类型数据时,就是返回一个成功状态的promise对象

async function fn(){
    return await 'ok';
} 
或
async function fn1(){
    return 'ok';
}
--以上两种情况都会返回一个成功的promise对象,并且该promise对象所携带的参数就是async函数所返回的普通数据类型的数据

 (3)点击 button获取验证码按钮回调

async getCode(e){//点击一次后将其变为disabled的30秒不能点击状态
        let reg=/^[\d]{11}$/;//手机号长度校验
        if(reg.test(this.phone)) {//手机号长度够了才可以走后面的 请求
          try {
            // let {phone}=this ;//从组件实例身上解构赋值 手机号这个数据
            //手机号有了,不为空,就执行后面的联系actions请求并传入手机号
            // phone && (await this.$store.dispatch('RegisterVc/getYanZhenCode',this.phone));
            await this.$store.dispatch('RegisterVc/getYanZhenCode', this.phone);//联系actions发请求,把电话传递给服务器
            this.code = this.yanZhenCode;//使用映射过来的数据
            e.target.disabled = true;//禁用
            e.target.style.cursor = 'not-allowed';
            let s = 10, timer = null;
            timer = setInterval(() => {
              this.btnCodeText = s;
              s--;
              if (s < 0) {
                e.target.disabled = false;//解除禁用
                this.btnCodeText = '获取验证码';
                e.target.style.cursor = 'pointer';
                clearInterval(timer);
              }
            }, 1000);//每一秒执行一次定时器中的函数
          } catch (err) {
            // alert(err.message)
            console.log(err)
          }
        }
        else{
          alert('手机号码不符合规定')
        }
      },

--这里回调主要是联系actions对应函数,发请求,传递手机号过去

--在这里使用了正则校验输入的号码长度

--使用try catch捕获dispatch联系actions中函数返回的状态的错误

--e.target.dispatch=true 禁用

--这里请求成功服务器会返回数据 验证码【正常情况下是服务器发送短信到对应手机号码的用户手机上】

使用:axios 、vuex、脚手架代理、模块化、模板字符串、 async与await、Promise、dispatch、v-model、正则表达式、定时器、事件对象、点击事件、methods配置项、mapState映射组件仓库数据

 3、点击注册按钮部分

注册部分要传递 手机号码 ,验证码 ,密码(三个必选项)到服务器

(1)配置axios实例 

//用户注册  /api/user/passport/register  传手机号,密码,验证码给服务器 ,如果手机号未被注册会被存入数据库中
export const reqUserRegister=(data)=>{//接收actions中调用此函数返回过来的表单参数
    return axs({
        method:'post',
        url:'/api3/user/passport/register',
        data,//传给服务器
    })
}

--这里我们使用axios中data属性传递给服务器

--路径中的/api3,走的是 'api3'代理,解决跨域

 (2)使用对应组件vuex小仓库(集中式状态管理)

async getUserRegister(_,user) {//因为只是把注册表单数据传递给服务器 存入数据库中,不会返回数据,不需要使用commit联系mutations,使用占位符占一个store位置。
        let response=await reqUserRegister(user)
        if(response.code===200){//根据服务器返回的状态
            return 'ok'; //async函数返回一个普通类型数据时,都是一个成功的promise对象返回
        }
        else{
            return Promise.reject(new Error('err'));
        }
    }

--(在dispatch联系actions此函数传)这里接收表单用户数据信息,并传给reqUserRegister函数

--根据服务器返回的数据状态,async返回返回相应成功或失败(抛出错误)的promise对象

 (3)点击注册后的回调

这里主要就是拿收集好的表单用户数据,通过dispatch联系actions对应async函数时传入参数

async userRegister(){
          //解构实例身上收集的表单数据
        let {phone,code,password,password1} =this;
        //表单数据都不为空,就走后面,联系actions发请求传参数【表单用户注册数据】  对象属性属性值的简写形式传参 ,联系actions请求函数会返回一个成功或失败的promise对象
        try{
          (phone && code && password===password1) && await this.$store.dispatch('RegisterVc/getUserRegister',{phone,code,password});//这里要传递参数
          //成功以后【服务器将表单用户注册数据存入数据库中】进行路由跳转到登陆页面
          this.$router.push({
            name:'login'
          })
        }
        catch(err) {//请求传参给服务器失败【服务器没有把用户信息存入数据库中】,可能是用户电话已被注册
          alert(err.message)
        }
      }

--根据dispatch联系actions对象中对应async函数所返回的成功或失败的promise对象【抛出错误】使用try catch捕获错误 ,成功进行路由跳转【编程式路由导航】(服务器就会把用户数据存入数据库中)。

--这里服务器不会给我们返回数据,只是根据所传递的参数【手机号码,验证码,密码】给我们注册【数据库中操作】

使用:axios、vuex、 事件回调、dispatch

二、登录部分 

1、

已经注册成功的用户信息【账号密码】传入服务器后会被存入数据库中。
登录时,发请求把账号和密码传给服务器,服务器拿着账号与密码到数据库查询比对,如果一致的话进行下一步【看具体要干什么】--路由跳转到Home首页
【收集用户名与密码】
【配置axios 带参】
【配置vuex】
【点击登录按钮发请求】

--请求方式要正确 这里是post方式【写错的话就是201 错误了】
--所传递的参数要与接口文档参数名称要一致【不一致的话会返回202 参数不正确】
--别忘走代理 这里走的是api3代理 解决跨域
--成功的话,服务器会返回数据【包括token字符串令牌】

【请求路径错了会报错,返回失败的promise对象】
【请求方式写错了,不会报错,但会返回201 错误】
【请求成功了,用户信息有误,会根据信息的错误类型返回相应数据以及状态码】

【登陆业务】
----【token服务器返回的,用户身份唯一标识】(就像身份证)
----【一般情况下登录后,只会返回一个token令牌】
----【我们登陆后就是拿着token令牌到服务器要数据】

【注意】vuex存储数据不是持久化的,存的数据一刷新就没了   △△△△△△

 (1)配置axios 传递参数

//登录 /api/user/passport/login 传给服务器参数账号与密码为必选项
export const reqUserLogin=(data)=>{
    return axs({
        method:'post',//请求类型不要写错
        url:'/api3/user/passport/login',//走的是api3的代理
        data,
    })
}

这里使用axios中data传参方式 

 //用户登录  【服务器返回用户唯一身份标识token】【以后就拿着token令牌到服务器(验证)要对应用户数据】
     async getUserLogin({commit},user){
         let response= await reqUserLogin(user);//传参给服务器
         if(response.code===200){//请求成功,服务器返回token令牌
             commit('GETUSERLOGIN',response.data.token);//联系mutations,并传服务器返回的数据过去
             return 'ok';
         }
         else{
             return Promise.reject(new Error('err'));//状态码不是200【没有成功】,返回一个失败状态的promise对象到此async函数的调用处
         }

    },

--登录服务器会返回数据【token令牌】--用户的唯一身份标识、以后需要拿着token给服务器要对应用户数据

--请求成功 联系mutations并把token传递过去

--然后mutations对应函数把传递过来的token存入state中

(3)点击登录发请求【传用户信息】

 //登陆的回调
      async isLogin(){
        let {phone,password}=this;//解构赋值
        //前面两个都有就走后面,联系actions发请求,并把用户登录表单数据传给服务器
        try{
          (phone && password) && await this.$store.dispatch('RegisterOrLoginVc/getUserLogin',{phone,password})//这里传递的参数要与接口文档中的参数名一致
          //登录成功进行路由跳转
          this.$router.push({
            name:'home',
          })
          localStorage.setItem('token',this.token);//存在本地储存当中
          console.log(this.userRz)
        }
        catch(err) {
            alert(err.message);
        }
      }

 --点击登录按钮传收集的用户名与密码到dispatch所联系的actions对应请求的函数中,发请求

--await等待函数返回状态【根据请求成功与失败,函数返回成功与失败的promise对象】

--在这里我们mapState映射了小仓库state数据token,并存储在本地存储当中【请求成功我们存在state中的】

--成功进行路由跳转【到Home首页】

 

 

 2、登录后获取用户信息

--到这里的时候我们点击了登录按钮,登陆成功已经获取到了token令牌【用户唯一身份标识,以后拿着用于象服务器请求相应用户身份的数据信息】,并存在浏览器本地储存当中

--本地储存中有token的话,就表示用户点击了登录按钮,并且登录成功【就应该是一个登录的状态】

//登陆成功后 获取用户信息  /api/user/passport/auth/getUserInfo
export const reqUserInfo=()=>{
    return axs({method:'get',url:'/api3/user/passport/auth/getUserInfo'})
}

想要获取用户的信息,我们就要拿着登陆时服务器返回的token令牌【我们存在本地储存中】在请求拦截器config.headers.token请求头的字段设置请求头,这里我是从本地储存中拿的token令牌字符串【重点】

 //登录后 获取用户信息
    async getUserInfo({commit}){
        let response=await reqUserInfo();//返回一个成功或失败的promise对象
        if(response.code===200){
            commit('GETUSERINFO',response.data);//请求成功 联系mutations储存服务器返回的数据
            console.log(response.data)
            return 'ok'; 
        }
        //else if (response.code===208){//用户未登录【退出登录时,挂载发请求,带的是uuid字段请求            头】会报错,我们在这里处理
            //return ;//在这里不用单独处理错误  全局路由守卫调用的地方【使用await才可以】 catch会捕获到错误【token过期,或者请求头没有token】
        //}
        else{//请求不返回code为200的成功状态码,【请求头没有token,或token失效】
            return Promise.reject(new Error('err'));   
        }
       
    }

 --函数解构store对象中的commit联系mutations将服务器返回的登录后的用户信息传递过去

--mutations中把用户信息放到state中

 因为登陆成功后路由跳转到Home首页,我们在首页挂载完成时【mounted钩子中】,使用dispatch联系actions中对应获取用户登录信息的请求函数


      //登录成功后,路由跳转到首页 联系actions发请求 拿用户信息
      await this.$store.dispatch('RegisterOrLoginVc/getUserInfo');
  
   

【注意】:每次挂载都会发请求【如果有token字段的请求头(我们拿的是本地储存当中的)--用户已登陆】,获取用户信息,如果本地存储中没有token令牌表示用户未登录【请求头中就不会有token字段】服务器就不会返回用户数据,页面相应使用用户信息的地方就不会被渲染上。【服务器会拿着我么请求头中传过去的token进行校验】

--Header组件,根据用户信息数据name的有无,决定(登录|注册)与(用户名|退出登录)的显示与隐藏【如果有用户登录后的用户信息数据中name,表示用户已经登录,就需要展示(用户名|退出登录)】,请求头没有传token字段,服务器就不会返回用户数据信息,更拿不到数据中的name属性,这里使用了v-if="!userName" 【有了就是true,我们给他取反让(登录|注册)隐藏】,与v-else

--header组件这里是根据用户信息数据显示的,用户信息数据想要有的话,就必须使用对应获取用户信息的接口 ,发请求【并在请求头上携带token字段--服务器校验用户身份】

 这里因为只在Home组件挂载完成时,发请求【有无token请求头 有就带上表示用户已登录】,拿用户数据放到注册与登录小仓库中,所以我们在Home组件每次刷新,Header组件中的用户信息都不会丢失【这里就当用户已登录请求头中有token】

三·、退出登录部分 

要退出登录,发请求给服务器,服务器会删除对应的token【当用户退出登录后,服务器会使其之前颁发的令牌(token)无效化,这就意味着,退出登陆后,我们在拿着服务器之前颁发的token令牌作为请求头字段的话发请求(获取用户数据),就不会成功获取对应用户息】

--发请求告诉服务器要退出登录,服务器删除对应token

--删除本地存储中的token【发请求后,此token就已经无效了,就不需要放到本地存储中了】

--删除注册与登录组件小仓库中的userInfo用户信息【这里是在mutations中操作的state删除的】

--根据actions中的退出函数,返回的状态,使用try 与catch捕获,没有捕获到错误,表示code===200,退出登录成功,进行路由跳转到Home首页。

 

四、路由守卫 

--用户登录以后【就不能登录了--不能够出现登录界面--用户在url地址输入login不能让他跳到登录界面】
--用户没有登录,就不能跳转到购物车
路由守卫的第三个参数next【放行】
next(false): 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/home')一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像你调用 router.push() 一样。

 <1>组件内路由守卫【用户已登录,不允许通过router-link或者编程式路由导航以及手动修改url跳转到登录页面】

 //组件内路由守卫   用户已登录时,就不让他再次进入登录界面了
    beforeRouteEnter(to,from,next){
      if (localStorage.getItem('token')){//有token
        next(false);//如果用户已登陆,用户在url地址中输入login跳转,会阻断跳转 【没有登录的时候本地存储中没有token,就可以进入login组件】
        // console.log(to,from,next);
      }
    }

用户已登陆,要让Header组件展示用户信息【发请求】

--每个路由组件挂载的时候,发请求带token,拿用户信息

--在App组件挂载完成时,发请求拿用户信息【刷新才有】

--在Header组件挂载完成时,发请求拿用户数据也可以

--全局路由守卫,当要to的路由组件时,判断有无用户信息,有直接next,没有发请求带token拿用户数据信息,再next

<2>使用全局前置路由守卫【控制控制已登陆的用户不允许跳到login组件】

//全局前置路由守卫
router.beforeEach(async (to,from,next)=>{
    //to:到哪去 from:从哪来 next:next()放行   ,next(path)--放行到指定路由组件
    //登录以后,就不允许用户跳到login组件
    //判断用户是否登录
    // next();
    // let token=store.state.RegisterOrLoginVc.token;//用户登录成功之后就会将服务器返回的token存在注册与登录组件的小仓库中
    let token=localStorage.getItem('token');
    let name=store.state.RegisterOrLoginVc.userInfo.name;//不能使用整个对象判断是否有用户数据,拿对象中的每个属性判断【空对象也是true】
    if(token){//小仓库中有token,用户已登陆
        //判断用户是否是去login登录或register注册组件 【登录后就不允许过去】
        if (to.path==='/login' || to.path==='/register'){
            next('/home');//不让去,回到home首页
        }
        else{//用户去的是除了登录与注册组件的其他路由组件
            //在这里我们解决每一个路由组件挂载时带着token拿用户数据【放到注册与登录组件的仓库中userInfo】这一重复性操作
            //判断注册与登录组件小仓库中是否有用户数据--为了展示Header组件对应的用户数据
            if (name){//有用户数据,可以展示Header中的对应用户数据【用户名 | 退出登录】
                console.log('@@',name);
                next();
                // store.state.RegisterOrLoginVc.userInfo={};
            }
            // else {
            //     next();//如果使用Header组件挂载发请求,获取用户数据使用
            // }
            else {//没有用户数据,Header中的用户信息展示不上
                //发请求【请求头带着token字段】,拿用户数据
                try {
                   let res=await store.dispatch('RegisterOrLoginVc/getUserInfo');//拿用户数据,放在注册与登录组件小仓库中
                    console.log('@@',res)
                    //等待用户数据放进去之后 放行
                    next();
                }
                
                catch(err) {//请求用户数据失败【请求时没有带token请求头字段 或 token过期】
                    //删除本地储存中的token,以及用户数据【注册与登录组件小仓库中的】
                    await store.dispatch('RegisterOrLoginVc/getUserLogout');//这里必须使用await
                    next('/login')
                    alert('认证过期或用户未登录')
                }
            }
        }
    }
    else{//未登录
        //未登录 不允许用户去:交易页【trade】 ,支付页【pay ,paysuccess】 ,个人中心【center】
        let toPath=to.path;//用户要去的路径                                    //路径带有center就算为个人中心【因为有二级路由组件】
        if(toPath==='/trade' || toPath==='/pay' || toPath==='/paysuccess' || toPath.indexOf('/center')>=0){
            //用户未登录想要去这些路由组件,就先跳到登陆界面让用户登陆
            next(`/login?wanto=${toPath}`);//跳到登陆页面之后,如果用户登陆了,就在跳到用户想要去的地方。 这里利用路由传参把要to的路径【传给login路由组件】
        }
        else{//非交易页 支付页 个人中心就可以去 放行
            next();
        }
    }

 点击登陆成功路由跳转的路径。

         let toPath=this.$route.query.wanto || '/home';//如果有用户要to的路由地址,就跳到用户要去的地方【用户未登陆点击一个要去的地方存在query中】,没有就默认跳转到home首页

 

--判断用户是否登陆【本地储存中的token】

--如果用户登陆,不允许跳到登陆或注册路由组件【根据to】

--如果用户登陆,要去非登陆与注册组件【判断有无用户数据信息】,有就放行,没有就发请求拿用户数据信息【这里请求如果被catch捕获,可能是token过期,或者请求头没带token字段(用户手动删除)】,我们就发请求删除token(用户数据,本地存储的token)

五、交易页Trade【购物车点击结算】

要登录,有token

--购物车点击结算进行路由跳转

--Trade路由组件挂载发请求,拿数据【mock的用户收货地址】【请求服务器的购物商品清单--里面包含订单编号】

--拿着数据进行渲染

--收货地址点击变为默认地址,排他思维【给回调函数传存放整个收货地址数据的数组,以及点击的那个收货地址所对应的数组元素v-for遍历出来的】

--右下角展示当前点击默认收货地址【先计算出来,数组方法find条件是isDefault===1,数组find方法不会像filter方法一样返回数组 里面放的满足条件的对象,find方法直接会返回满足条件的数组元素】

computed:{
      ...mapState('TradeVc',['addressinfo']),//映射用户收货地址数据
      //计算出当前的默认收货地址
      defaultAddress(){
         return this.addressinfo.find(item=>{
          return item.isDefault===1;//等于1,就是默认的地址,最下面展示这个 ,会返回满足条件的数组元素【数组的形式返回】 ,可以用find()
        }) || {};//默认返回一个空对象
      },

 点击提交订单

--发请求【带上挂载时请求商品请求数据中的订单编号】【收货人姓名,电话,收货地址,支付方式,买家留言,商品清单数组】,服务器会返回订单号。

--路由跳转到Pay路由组件,传一个订单号过去。

六、支付页Pay【交易页点击提交订单】

挂载完成,发请求【拿着路由跳转传的订单号,传给服务器】拿支付页的相关数据展示【会返回一个生成支付二维码的字符串】。

注意生命周期钩子函数不能使用async与await ,我们把发请求单独放在methods中定义的函数【async函数】,挂载时就调用这个函数。

 

 

微信支付业务 

(1)二维码

安装引入qrcode   会将二维码字符串,生成二维码。

npm install --save qrcode

es6中的模块化引入

import QRCode from 'qrcode'
// With promises
QRCode.toDataURL('I am a pony!')//会返回一个带有状态的promise对象,成功的话就带有二维码图片
  .then(url => {
    console.log(url)
  })
  .catch(err => {
    console.error(err)
  })

// With async/await
const generateQR = async text => {
  try {
    console.log(await QRCode.toDataURL(text))//会返回一个带有状态的promise对象,成功的话就带有二维码图片
  } catch (err) {
    console.error(err)
  }
}

 会返回一个带有状态的promise对象,里面带有生成的二维码图片。

 (2)点击立即支付【弹窗】

element-ui的按需引入 ,资源不会过大。

npm i element-ui
npm install babel-plugin-component -D
配置bable.config.js文件
--使用弹窗组件
import {MessageBox} from 'element-ui';
Vue.prototype.$alert=MessageBox.alert;//在vm的beforeCreate()生命周期钩子中
Vue.prototype.$msgbox = MessageBox;//在vm的beforeCreate()生命周期钩子中
<el-button type="text" class="btn" @click="open">立即支付</el-button>  --使用

 el组件的相关配置,官网每个组件对应都会有相关配置参考。

组件实例vc.__proto__.__proto__=== Vue.prototype ;

也就是VueComponent构造函数原型对象的__proto__指向Vue的原型对象【所以vc组件实例对象可以使用Vue身上的属性与方法】

点击【立即支付】弹窗弹出 ,支付二维码展示,我们需要知道用户的支付状态--服务器知道【发请求问服务器】。如果只发一次请求【在这个时候用户还没有支付?】,所以我们要不断的发请求【询问服务器用户支付状态】,就要用到定时器。

请求返回状态码200,用户支付成功

--清除我们开启的定时器

--状态码为200时,存一个状态码【为了在后面判断用户点击我已支付时的--依据】

--关闭弹窗

--路由跳转到支付成功界面

用户点击弹窗【支付遇到了问题】或【我已支付】

参考element组件的配置属性【官网中】
beforeClose(type,elVc,done){}
//type:返回用户点击的那个按钮  cancel用户点击支付遇到问题 ,  confirm用户点击我已支付
//elVc:element-ui组件实例
//done:关闭弹窗
--首先根据type判断用户点击了哪个按钮
--如果type 为cancel用户点击支付遇到问题 :弹出提示框提示用户,清除定时器【停止发请求】,关闭弹窗
--如果type 为confirm用户点击我已支付 :这时就需要知道用户是否支付成功,因为我们不断发请求,询问服务器用户是否支付成功,如果用户支付成功【根据服务器返回的数据code状态码200,清除定时器,停止发请求,存一个成功的状态码△,关闭弹窗,路由跳转】,存到data中的状态码就派上了用场【就是根据这个判断】,如果data中的状态码为200【表示用户支付成功】,清除定时器【停止发请求】,关闭弹窗,路由跳转。

 

<el-button type="text" class="btn" @click="open">立即支付</el-button>
data(){
      return{
        payInfo:{},//请求返回的数据为对象形式,在这里初始为一个空对象
        timer:null,//待存定时器
        paystatusCode:'',//待存支付成功状态码200 ,以后点击我已支付按钮的时候,根据这个是否为200,判断用户是否支付成功,【路由跳转】
      }
    },
//查询订单支付状态  /api/payment/weixin/queryPayStatus/{orderId}  ,弹窗弹出,用户要支付的时候,就要不断发请求问服务器 用户的支付状态
export  const reqPayStatus=(orderId)=>{
    return axs({method:'get',url:  `/api3/payment/weixin/queryPayStatus/${orderId}`});//不要忘记走代理
}

methods配置对象中 

 async open() {
        let qrCodeurl=await QRcode.toDataURL(this.payInfo.codeUrl);//返回一个带有状态的promise对象  【带有二维码】,把二维码,发到弹出框中
        this.$alert(`<img src=${qrCodeurl} alt=""/>`, '微信支付', {
          dangerouslyUseHTMLString: true,
          center:true,//对应组件都有相关的配置项
          showCancelButton:true,//显示取消按钮
          cancelButtonText:'提交问题',//取消的文本
          confirmButtonText:'支付成功',//确定按钮文本
          showClose:false,//隐藏关闭按钮
          beforeClose:(type,elVc,done)=>{//官网中找的对应组件配置都有
            // type :cancel用户点击支付遇到问题 ,  confirm用户点击我已支付
            //elVc:element-ui这个弹框组件
            //done() :关闭弹窗
            if(type==='cancel'){//用户点击支付遇到问题
              alert('请联系后台管理员老师');//提示用户
              clearInterval(this.timer);//清除定时器【停止发请求】
              this.timer=null;
              done();//关闭弹窗
            }  
            //状态码不为200【用户不支付成功】,不会执行后面的
            else if(type==='confirm' && this.paystatusCode===200){//用户点击我已支付 ,根据状态码判断用户是否支付【状态码不是200,点击按钮 无效】
              clearInterval(this.timer);
              this.timer=null;
              done();//关闭弹窗
              this.$router.push({name:'paysuccess'});
            }
          }
        });
        //弹窗弹出以后,要知道用户的支付状态  ,服务器知道,所以就要不断发请求 询问服务器用户支付状态
        //因为要不断向服务器询问 支付状态 使用定时器
        this.timer=setInterval(async ()=>{
          let response=await this.$Api.reqPayStatus(this.$route.query.dingdanId);//返回带有状态带有数据的promise对象【在这里服务器不会返回数据】
          console.log(response)
          if(response.code===200){//状态码为200表示支付成功
              //清除定时器 不在发请求
            clearInterval(this.timer);
            this.timer=null;
            //把状态码200存起来
            this.paystatusCode=200;
            //隐藏弹窗
            this.$msgbox.close();
            //路由跳转
            this.$router.push({name:'paysuccess'})

          }
        },1000);

      }

还有就是用户登录了不能随便去交易页【trade】,支付页【pay】,支付成功页【paysuccess】

用户去交易页【必须从购物车去】
用户去支付界面【只能从交易页去】
用户去支付成功界面【只能从pay支付页面去】

使用独享路由守卫或者组件内路由守卫。

 写在对应路由【trade】配置项中:

beforeEnter(to,from,next){
                //用户想要去交易页,必须从购物车去【】看用户是否是从购物车来的】
                if(from.path==='/shopcart'){
                    next();//只管交易页
                }
                else {
                    next(false);//还是为当前页 来的路径不是'/shopcart',就会被阻断,并且路径还是from的path
                }
            }

 补充组件内路由守卫【detail组件为例】:

 //组件内路由守卫 同一个路由路径,但是后面的参数更新,就会调用
     beforeRouteUpdate(to,from,next){// 在当前路由改变,但是该组件被复用时调用  /detail/12   /detail/9 共用的/detail后面的值变,就会触发【路径从/detail/12 跳到/detail/9】就会调用此组件内路由守卫
       console.log('@更新')
     },

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值