vue前台(九)

一,购物车的删除

1.封装请求删除购物车商品函数

//请求删除购物车商品  /api/cart/deleteCart/{skuId}   delete
export const reqDeleteCart = (skuId) => Ajax.delete(`/cart/deleteCart/${skuId}`)

2.在vuex中定义发送请求

//删除一个
  async deleteShopCart({commit},skuId){
    const result = await reqDeleteCart(skuId)
    if(result.code === 200){
      return '删除成功'
    }else{
      return Promise.reject(new Error('删除失败'))
    }
  },

3.在组件中模板中点击删除按钮,dispatch到vuex中,调用删除的请求,然后在调用发送页面数据的请求,获取新数据

 <a href="javascript:;" class="sindelet" @click="deleteCart(cart)">删除</a>

回调

//删除单个的购物车商品
      async deleteCart(cart){
        try {
          await this.$store.dispatch('deleteShopCart',cart.skuId)
          //重新发送请求,获取页面数据
          this.getShopCartList()
        } catch (error) {
          alert(error.message)
        }
      },

 

4.点击删除选中的商品交互逻辑,点击删除按钮,在vuex的actions中定义一个函数deleteCheckedShopCart,作用,遍历每一条信息,然后对选中的每一条商品,dispatch到,删除一个商品的函数(里头是删除商品的请求)。达到对选中的商品进行删除,然后在发送页面数据请求
 
 
4,1 点击删除选中按钮,
<a href="javascript:;" @click="deleteChecked">删除选中的商品</a>

回调

//删除选中的多个购物车商品
      async deleteChecked(){
        try {
          await this.$store.dispatch('deleteCheckedShopCart')
          //重新发送请求,获取页面数据
          this.getShopCartList()
        } catch (error) {
          alert(error.message)
        }
      }

4.2,在vuex中处理删除商品的逻辑

  //删除一个
  async deleteShopCart({commit},skuId){
    const result = await reqDeleteCart(skuId)
    if(result.code === 200){
      return '删除成功'
    }else{
      return Promise.reject(new Error('删除失败'))
    }
  },

 // 删除多个
  deleteCheckedShopCart({commit,dispatch,state}){
    let promises = []
    state.shopCartList.forEach(item => {
      // 没选中的不发送删除请求
      if(!item.isChecked) return 
      // 选中的发送删除请求
      let promise = dispatch('deleteShopCart',item.skuId)
      promises.push(promise)
    })

    return Promise.all(promises)
  }

 

 

二,注册和登录静态页面实现和准备工作,购物车完成,点击结算按钮,应该去创建订单页面

注,src-assets,该文件夹是保存的公共的静态资源,比如图片

登录和注册页面有连接按钮可以互相跳转,需要在各自组件中配置连接路由

 

1,注册的逻辑及验证码的处理

1,1  封装请求注册接口函数

//请求注册 /api/user/passport/register  post

export const reqRegister = (userInfo) => Ajax.post('/user/passport/register',userInfo)

1,2在vuex,user.js中发送请求

const actions = {
  async userRegister({commit},userInfo){
    const result = await reqRegister(userInfo)
    if(result.code === 200){
      return '注册成功'
    }else{
      return Promise.reject(new Error('注册失败'))
    }
  },

1,3,在组件中,点击完成注册按钮,dispatch到vuex,发送注册请求,然后跳转到登录页面

<div class="btn">
        <button @click="register">完成注册</button>
      </div>

回调

 async register(){
        let {mobile,password,code,password2} = this
        if(mobile&&password&&code&&password2&&password === password2){
          let userInfo = {mobile,password,code}
          try {
            await this.$store.dispatch('userRegister',userInfo)
            alert('注册成功,自动跳转登录页面')
            this.$router.push('/login')
          } catch (error) {
            alert(error.message)
          }
        }
      },

 

注:根据api文档,收集
 <input type="text" placeholder="请输入你的手机号" v-model="mobile">
<input type="text" placeholder="请输入确认密码" v-model="password2">
<input type="text" placeholder="请输入验证码" v-model="code">
      <input type="text" placeholder="请输入确认密码" v-model="password2">

 

请求体对象userInfo中的参数,
data(){
      return {
        mobile:'',
        password:'',
        code:'',
        password2:'',
      }
    },

  <!-- 这两种都是ok的,上面的使用的是img图片的src特殊性,发送的普通请求  不跨域 -->
        <!-- 下面我们使用的是代理服务器转发的,我们认为是跨域的 -->
        <!-- <img ref="code" src="http://182.92.128.115/api/user/passport/code" alt="code" @click="changeCode"> -->
        <img ref="code" src="/api/user/passport/code" alt="code" @click="changeCode">

1,4点击验证码图片,重新设置src地址

   changeCode(){
        this.$refs.code.src = '/api/user/passport/code'
      }

 

 三,用户登录逻辑处理

登录:
        
        静态组件
        api
        store
        收集数据发送请求
        请求成功后需要把用户信息保存在localStorage用于自动登录
        state的用户信息也要修改,
        state的用户信息读取先从localStorage里面去读,没有就是{},通过登录去修改
        以后每次发请求都要携带这个用户信息的token
        修改头部的用户状态信息

 

1.封账登录接口的函数,userinfo为请求体,需要收集登录账号,和密码

//请求登录 /api/user/passport/login   post

export const reqLogin = (userInfo) => Ajax.post('/user/passport/login',userInfo)

 

 在user.js中的vuex中的actions发送登录请求

 //登录发送请求
  async userLogin({commit},userInfo){
    const result = await reqLogin(userInfo)
    if(result.code === 200){
      //把用户的信息保存起来,为了自动登录(下次再来还可以找到登录状态的用户信息)
      localStorage.setItem('USERINFO_KEY',JSON.stringify(result.data))
      commit('RECEIVEUSERINFO',result.data)
    }
  },

 

在mutations中配置数据

const mutations = {
  RECEIVEUSERINFO(state,userInfo){
    state.userInfo = userInfo
  },
const state = {
  userTempId:getUserTempId(),
  userInfo: JSON.parse(localStorage.getItem('USERINFO_KEY')) ||{}
}

 

 

2.在登录login组件中,收集登录账号和密码. 

注:在form表单中,是有默认提交跳转功能的,而button,默认时点击跳转的按钮,此时,需要阻止其默认行为,在vue中需要用到事件修饰符

 
<form>
              <div class="input-text clearFix">
                <span></span>
                <input type="text" placeholder="邮箱/用户名/手机号" v-model="mobile" />
              </div>
              <div class="input-text clearFix">
                <span class="pwd"></span>
                <input type="text" placeholder="请输入密码" v-model="password" />
              </div>
              <div class="setting clearFix">
                <label class="checkbox inline">
                  <input name="m1" type="checkbox" value="2" checked />
                  自动登录
                </label>
                <span class="forget">忘记密码?</span>
              </div>
              <button class="btn" @click.prevent="login">&nbsp;&nbsp;</button>
            </form>

 

在data中初始化mobile,password为空。 并且点击登录按钮dispatch到vuex. 

 async login() {
      let { mobile, password } = this;
      if (mobile && password) {
        let userInfo = { mobile, password };
        try {
          await this.$store.dispatch("userLogin",userInfo);
          alert('登录成功,跳转到首页去了')
          this.$router.push('/home')
        } catch (error) {
          alert(error.message)
        }
      }
    }

 

 
四,顶部用户登录状态信息展示

 

 

该html在header组件中,
1. 具体逻辑,从vuex中获取登录返回的信息userInfo,  
 
 computed:{
    //从用户的state当中获取用户信息
    ...mapState({
      userInfo:state => state.user.userInfo
    })
  },

2.然后新建一个p标签,通过登录账号,以及 v-if, v-else,逻辑来判断用户是否登录成功

     <!-- 判断用户是否是登录状态,如果是显示这个p -->
          <p v-if="userInfo.name">
            <a href="javascript:;">{{userInfo.name}}</a>
            <a href="javascript:;" class="register" @click="logout">退出</a> 
          </p>

          <!-- 如果用户不是登录状态,显示这个p -->
          <p v-else>
            <span></span>
            <router-link to="/login">登录</router-link>
            <!-- <a href="###">登录</a> -->
            <router-link to="/register" class="register">免费注册</router-link>
            <!-- <a href="###" class="register">免费注册</a> -->
          </p>

 

五,用户自动登录的逻辑, 需要把登录请求返回的数据,保存起来,下次再次登录的时候,可以自动登录,可以把信息保存在浏览器的localStorage,登录后,再次刷新,登录状态就会一直存在
 
 
  //登录发送请求
  async userLogin({commit},userInfo){
    const result = await reqLogin(userInfo)
    if(result.code === 200){
      //把用户的信息保存起来,为了自动登录(下次再来还可以找到登录状态的用户信息)
      localStorage.setItem('USERINFO_KEY',JSON.stringify(result.data))
      commit('RECEIVEUSERINFO',result.data)
    }
  },
const state = {
  userTempId:getUserTempId(),
  userInfo: JSON.parse(localStorage.getItem('USERINFO_KEY')) ||{}
}

 

 六,用户退出登录逻辑
 
1.封装退出登录请求函数
//请求退出登录 /api/user/passport/logout  get
export const reqLogout = () => Ajax.get('/user/passport/logout')

 

 2.退出登录逻辑, 发送ajax,退出登录,此时登录的信息userInfo,需要清空,而且localStorage里的数据也要清空
在vuex中发送退出登录的请求
  async userLogout({commit}){
    const result = await reqLogout()
    if(result.code === 200){
      //退出成功后,去清除state.userInfo的信息  变为{}
      // 还要去清除localStorage里面用户信息
      localStorage.removeItem('USERINFO_KEY')
      commit('RESETUSERINFO')
    }
  }

 

 在mutation中清空userInfo
  RESETUSERINFO(state){
    state.userInfo = {}
  }

在header组件中,点击退出登录按钮,dispatch到vuex,退出后,跳转到home页

<!-- 判断用户是否是登录状态,如果是显示这个p -->
          <p v-if="userInfo.name">
            <a href="javascript:;">{{userInfo.name}}</a>
            <a href="javascript:;" class="register" @click="logout">退出</a> 
          </p>

js逻辑

  //退出登录
    async logout(){
      try {
        await this.$store.dispatch('userLogout')
        alert('退出成功,自动跳到首页')
        this.$router.push('/home')
      } catch (error) {
        alert(error.message)
      }
    }

 

七,用户登录后的token携带(token和 userTempld区别)及跳转到trade页面
 
1.在请求拦截器中,配置用户登录的token,为什么配置呢,在请求头中配置token,后台记录该唯一值,以后用户在购物车添加商品,该信息都保存在这个token中。
先引入vuex,
import store from '@/store'
//请求拦截器内部一般不会处理错误的信息
service.interceptors.request.use(config => {
  //config是发送请求的配置对象,必须处理完返回这个配置对象
  //开启我们的进度条
  NProgress.start()

  //在请求头当中添加用户的临时id,让每个ajax请求都带着这个userTempId(购物车)
  let userTempId = store.state.user.userTempId
  if(userTempId){
    config.headers.userTempId = userTempId
  }

  //添加用户登录过后的token信息,让每个ajax请求都带这个token,为了找到用户登录后相关信息(订单、购物车)
  let token = store.state.user.userInfo.token
  if(token){
    config.headers.token = token
  }


  return config
});

注,登录状态下,每次发送请求,请求头都会携带该token

 

 

 userTempId( 临时id,)和token的区别

userTempId 未登录状态下的用户身份识别标识

token 登录状态下的用户身份识别标识
两个都存在的话,后台会合并临时id和对应信息到token对应的信息上,主流电商都会这么搞

 
发送登录请求,返回的响应结果,里头有一个token

{

code: 200

message: "成功"

data:{

nickName:"Administrator",

name:"Admin",

token: 90aa16f24d04c7d882051412f9ec45b"

}

ok: true

}
 
 
 
 八,在shopcart组件中,点击结算按钮,跳转到订单页面,trede组件
 
html页面
<div class="sumbtn">
          <router-link to="/trade" class="sum-btn">结算</router-link>
          <!-- <a class="sum-btn" href="###" target="_blank">结算</a> -->
        </div>

 

 
 
 
 
 
 
 
 
 

 

 

 

 
posted @ 2020-07-31 06:47  全情海洋  阅读(323)  评论(0编辑  收藏  举报