zoukankan      html  css  js  c++  java
  • 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>
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    js的浅拷贝与深拷贝
    用Nodejs连接MySQL(原文链接)
    HTML5交互性图表库
    GitHub Desktop离线安装包
    docker--Dockerfile--sonarqube
    docker --Nexus仓库
    docker --Dockerfile--一些语法
    zookeeper 四字命令
    docker --swarm创建一个集群
    docker --swarm启动2375端口监听
  • 原文地址:https://www.cnblogs.com/fsg6/p/13407589.html
Copyright © 2011-2022 走看看