Vue2项目实战--b站尚硅谷--尚品汇项目--详细笔记--day10

登入注册静态组件

assets文件夹----存放全部组件共用的静态资源-----打包时候消失,在组件中

在样式文件也可以使用@符号【src别名】,切记在前面加上~【小波浪】

//之前listcontainer中用到icons图片---同一放到assets中
background-image: url(~@/assets/images/icons.png);

注册业务

  data() {
    return {
      // 收集表单数据--手机号
      phone: "",
      //验证码
      code: "",
    };

v-model="phone"
v-model="code"

//1 api   
//获取验证码
//URL:/api/user/passport/sendCode/{phone}  method:get
export const reqGetCode = (phone)=>requests({url:`/user/passport/sendCode/${phone}`,method:'get'});
//2 新建user小仓库,记得到大仓库中去注册
import user from './user'
      
//一、获取验证码----actions中
async getCode({ commit }, phone) {
  //获取验证码的这个接口:把验证码返回,但是正常情况,后台把验证码发到用户手机上
  let result = await reqGetCode(phone);
  if (result.code == 200) {
    commit("GETCODE", result.data);
    return "ok";
  } else {
    return Promise.reject(new Error("faile"));
  }
},
//二
GETCODE(state, code) {
    state.code = code;
},

code: "",


//3 回到组件中----@click="getCode"
<button style="width:100px;height:38px" @click="getCode">获取验证码</button>
//methods中
//获取验证码
async getCode() {
  //简单判断一下---至少用数据
  try {
    //如果获取到验证码
    const { phone } = this;
    phone && (await this.$store.dispatch("getCode", phone));
    //将组件的code属性值变为仓库中验证码[验证码直接自己填写了]
    this.code = this.$store.state.user.code;
  } catch (error) {}
},

其他的表单数据也要

//收集用v-model绑定
data() {
    return {
      // 收集表单数据--手机号
      phone: "",
      //验证码
      code: "",
      //密码
      password: "",
      //确认密码
      password1: "",
      //是否同意
      agree: true,
    };
  },

完成注册

//1   @click="userRegister" 
<button @click="userRegister">完成注册</button>

// api--index
//注册
//url:/api/user/passport/register  method:post    phone code password
export const reqUserRegister = (data)=>requests({url:'/user/passport/register',data,method:'post'});

//2 仓库
//用户注册
async userRegister({ commit }, user) {
  let result = await reqUserRegister(user);
  if (result.code == 200) {
    return "ok";
  } else {
    return Promise.reject(new Error("faile"));
  }
},
//3 组件
//用户注册
async userRegister() {
  const success = await this.$validator.validateAll();
  //全部表单验证成功,在向服务器发请求,进行祖册
  //只要有一个表单没有成功,不会发请求
  if (success) {
    try {
      const { phone, code, password, password1 } = this;
      await this.$store.dispatch("userRegister", {
        phone,
        code,
        password,
      });
      //注册成功进行路由的跳转
      this.$router.push("/login");
    } catch (error) {
      alert(error.message);
    }
  }
},

登入页面

//也要搜集登入名和密码  v-model绑定
data() {
  return {
    phone: "",
    password: "",
  };
},

//登入的接口 api
//登录
//URL:/api/user/passport/login  method:post phone password
export const reqUserLogin = (data)=>requests({url:'/user/passport/login',data,method:'post'});

//仓库
//ations中
async userLogin({ commit }, data) {
  let result = await reqUserLogin(data);
  //服务器下发token,用户唯一标识符(uuid)
  //将来经常通过带token找服务器要用户信息进行展示
  if (result.code == 200) {
    //用户已经登录成功且获取到token
    commit("USERLOGIN", result.data.token);
    //持久化存储token---setToken这个是封装的,调用时记得先引入
    setToken(result.data.token);
    return "ok";
  } else {
    return Promise.reject(new Error("faile"));
  }
},
      
 //mutation中
USERLOGIN(state, token) {
	state.token = token;
},
//state中---注意 这里就不能直接写空串了,起始是空的,登入后有token,再刷新取原来token而不是空的,同样getToken是封装的
token: getToken(),

//派发请求 组件中   @click.prevent="userLogin"    prevent是阻止默认行为
<button class="btn" @click.prevent="userLogin">&nbsp;&nbsp;</button>

//methosd  登入成功跳到首页toPath
//注册,数据库存储用户信息---登入,登入成功时,后台为了验证身份,下发的令牌---一般服务器下发token,不带用户其他信息,前台持久化存储token
async userLogin() {
  try {
    //登录成功
    const { phone, password } = this;
    phone&&password&&(await this.$store.dispatch("userLogin", { phone, password }));
    //登录的路由组件:看路由当中是否包含query参数,有:调到query参数指定路由,没有:调到home
     let toPath = this.$route.query.redirect||"/home";
     this.$router.push(toPath);
  } catch (error) {
    alert(error.message);
  }
},

token是服务器下发给用户的唯一标识,就是服务器为了区分你是谁

登入业务

注册:通过数据库存储用户信息(名字,密码等)

  • 登入:登入成功后,服务器为了区分用户,服务器下发token(令牌:唯一标识)

  • 登入接口一般只返回token没有其他信息,前台需要持久化存储token(带着token找服务器要用户的信息进行展示)

  • 登入成功 每个页面都要展示用户信息—带着token找服务器要

之前uuid是我们自己造的,token是后台返回的

//api
//获取用户信息【需要带着用户的token向服务器要用户信息】
//URL:/api/user/passport/auth/getUserInfo  method:get 
export const reqUserInfo = ()=>requests({url:'/user/passport/auth/getUserInfo',method:'get'});

            
//要把token携带过去 请求拦截器里面---api--ajax
//需要携带token带给服务器
if(store.state.user.token){
  config.headers.token = store.state.user.token;
}


//仓库 三连环
//获取用户信息
async getUserInfo({ commit }) {
  let result = await reqUserInfo();
  if (result.code == 200) {
    //提交用户信息
    commit("GETUSERINFO", result.data);
    return 'ok';
  }else{
    return Promise.reject(new Error('faile'));
  }
},

GETUSERINFO(state, userInfo) {
	state.userInfo = userInfo;
},

userInfo: {},

//header中展示----userName(计算属性)
<p v-if="!userName">
	<span></span>
	<router-link to="/login">登录</router-link>
	<router-link class="register" to="/register">免费注册</router-link>
</p>
//导入成功什么时候派发呢,应该是home主页挂载完成,派发请求数据
userName(){
  return this.$store.state.user.userInfo.name;
}
<!-- 登录了 -->
<p v-else>
      <a>{{userName}}</a>
      <a class="register" @click="logout">退出登录</a>
</p>

一刷新home主页,获取不到用户的信息(因为vuex是非持久化存储)

//第一种写法,ok存好了,但是要用---         
localStorage.setItem('TOKEN', result.data.token)
//第二种写法,封装函数
//1--utils中
export const setToken = (token) => {
    localStorage.setItem('TOKEN', token)
}
//2 user仓库中
import { setToken } from '@/utils/token'
setToken(result.data.token)


//本地存了,但是再刷新home的时候,不能是token:'',应该找localStorage去拿,起始的时候也ok
token: localStorage.getItem('TOKEN'),---同理这个也可以封装成一个get函数

考虑home组件中,发送请求,应该放在那里—跳到search还是会丢失

解决方法一:在search也写一遍发请求,需要的组件都写一遍(太麻烦)

退出登入

//@click="logout" 
<a class="register" @click="logout">退出登录</a>

//通知服务器需要发请求 api
//退出登录
//URL:/api/user/passport/logout  get
export const reqLogout = ()=> requests({url:'/user/passport/logout',method:'get'});

//仓库中
//退出登录
async userLogout({commit}) {
  //只是向服务器发起一次请求,通知服务器清除token
  let result = await reqLogout();
  //action里面不能操作state,提交mutation修改state
  if(result.code==200){
    commit("CLEAR");
    return 'ok';
  }else{
    return Promise.reject(new Error('faile'));
  }
},

//清除本地数据
CLEAR(state){
  //帮仓库中先关用户信息清空
  state.token = '';
  state.userInfo={};
  //本地存储数据清空---也是封装好的函数调用
  removeToken();
}

//退出登录
async logout(){
  //退出登录需要做的事情
  //1:需要发请求,通知服务器退出登录【清除一些数据:token】
  //2:清除项目当中的数据【userInfo、token】
    try {
      //如果退出成功
      await this.$store.dispatch('userLogout');
      //回到首页
      this.$router.push('/home');
    } catch (error) {
      
    }
}

问题一:多个组件展示用户信息需要在每个组件的mounted中派发,太累了-----放在app里面第一次还没有

问题二:已经登入了就不可以回到登入页面

导航守卫

导航:路由发生跳转

守卫:全局【前置、后置、解析】、独享、组件内守卫

//路由中
//全局守卫:前置守卫(在路由跳转之间进行判断)
router.beforeEach(async (to, from, next) => {
  //to:获取到要跳转到的路由信息
  //from:获取到从哪个路由跳转过来来的信息
  //next: next() 放行  next(path) 放行  
  //方便测试 统一放行
  //  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('user/getUserInfo');
          next();
        } catch (error) {
          //token失效重新新登录
          await store.dispatch('user/userLogout');
          next('/login')
        }
      }
    }
  } else {
    //未登录:不能去交易相关、不能去支付相关【pay|paysuccess】、不能去个人中心
    //未登录去上面这些路由-----登录
    let toPath = to.path;
    if (toPath.indexOf('/trade') != -1 || toPath.indexOf('/pay') != -1 || toPath.indexOf('/center') != -1) {
      //把未登录的时候向去而没有去成的信息,存储于地址栏中【路由】
      next('/login?redirect=' + toPath);
    } else {
      //去的不是上面这些路由(home|search|shopCart)---放行
      next();
    }
  }
});

交易页面

拆分静态组件

配置路由

import Trade from '@/pages/Trade'

{
  path: '/trade',
  component: Trade,
  /* 只能从购物车界面, 才能跳转到交易界面 */
  beforeEnter (to, from, next) {
    if (from.path==='/shopcart') {
      next()
    } else {
      next('/shopcart')
    }
  }
},

给购物车结算按钮 绑定事件-路由页面跳转

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

交易页面中

//1 api
//获取用户地址信息
//URL:/api/user/userAddress/auth/findUserAddressList  method:get
export const reqAddressInfo = ()=>requests({url:'/user/userAddress/auth/findUserAddressList',method:'get'});

//2 在store中新建交易的小仓库
//actions中
//获取用户地址信息
async getUserAddress({ commit }) {
  let result = await reqAddressInfo();
  if (result.code == 200) {
    commit("GETUSERADDRESS", result.data);
  }
},

GETUSERADDRESS(state, address) {
	state.address = address;
},

address: [],
//上面这里主要,需要获取用户信息时,需要先登入
            
//仓库有了 派发请求 展示
this.$store.dispatch("getUserAddress"); 

获取订单交易详情页信息

//获取商品清单
//URL:/api/order/auth/trade   method:get
export const reqOrderInfo = ()=>requests({url:'/order/auth/trade',method:'get'});


//仓库 三连环
//获取商品清单数据
async getOrderInfo({commit}) {
  let result = await reqOrderInfo();
  if(result.code==200){
    commit("GETORDERINFO",result.data);
  }
},

GETORDERINFO(state,orderInfo){
	state.orderInfo = orderInfo;
}

orderInfo:{}

//组件中派发--展示
this.$store.dispatch("trade/getOrderInfo");

//捞数据---展示
import { mapState } from "vuex";
...mapState("trade", ["address", "orderInfo"]),
<!--接下来展示就可以了-->
<div
  class="address clearFix"
  v-for="(address, index) in addressInfo"
  :key="address.id"
>
  <span class="username " :class="{ selected: address.isDefault == 1 }">{{
    address.consignee
  }}</span>
  <p @click="changeDefault(address, addressInfo)">
    <span class="s1">{{ address.fullAddress }}</span>
    <span class="s2">{{ address.phoneNum }}</span>
    <span class="s3" v-show="address.isDefault == 1">默认地址</span>
  </p>
//@click="changeDefault(address, addressInfo)"
//修改默认地址
changeDefault(address, addressInfo) {
  //全部的isDefault为零
  addressInfo.forEach((item) => (item.isDefault = 0));
  address.isDefault = 1;
},
           
<!--同时修改下面最终的地址-->
//将来提交订单最终选中地址-----computed中
userDefaultAddress() {
  //find:查找数组当中符合条件的元素返回,最为最终结果
  return this.addressInfo.find((item) => item.isDefault == 1) || {};
},
//结构中展示
<div class="receiveInfo">
	寄送至:
	<span>{{ userDefaultAddress.fullAddress }}</span>
	收货人:<span>{{ userDefaultAddress.consignee }}</span>
	<span>{{ userDefaultAddress.phoneNum }}</span>
</div>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值