Vue2积分商城PC端项目(四)

目录

一、路由监听及其应用

1.1、路由监听的格式

1.2、路由监听的应用

二、组件重载

三、获取登录用户信息,请求头携带token

3.1、请求头携带token

3.2、获取用户登录信息

四、用户信息渲染

4.1、获取vuex中的图片img

五、删除token后的用户信息初始化

六、首页布局的套用

6.1、正向传值+数据最大长度控制的第一种方法

6.2、正向传值+数据最大长度控制的第二种方法


一、路由监听及其应用

现在登录状态下,如果我们手动删除token,切换路由的时候,购物车依然存在。这是因为登录状态依旧没有改变。

1.1、路由监听的格式

TopBar.vue中书写watch监听属性,监听"$route.path"的变化,可以检测是否有发生路由跳转。

watch: {
    // 监听路由的变化
    "$route.path": {
      handler(newVal, oldVal){
          // 什么时候执行这里的代码?? 路由发生变化的时候
      	  console.log(newVal, oldVal);
      }
    }
},

1.2、路由监听的应用

所以,我们可以把TopBar.vue中的created的代码封装起来,看做是设置用户登录状态的函数,封装在methods中

created(){
  	this.setUserLoginstatus()
},
watch: {
    // 监听路由的变化
    "$route.path": {
          handler(newVal, oldVal){
                // console.log(newVal, oldVal)
                if(newVal !== oldVal){
                 this.setUserLoginstatus()
                }
          }
    }
},
methods:{
    setUserLoginstatus(){
      	// 微信登录第二步:临时票据code换取token
    	let mycode = this.$route.query.code;
        if (mycode) {  
           ...
        }else{
         ...
        }
    },
}

二、组件重载

之前做的利用路由监听完成切换路由就更新用户登录状态值。

实质:监听路径的变化,重新渲染Topbar上的用户数据,在路径发生变化时执行的操作。

这个功能,也可以使用组件重载的方式来完成。即每次切换路由,我们都让TopBar.vue重新加载一次。

首先,现在TopBar的created函数中补充更新用户状态值的代码(此时注释掉前面的watch):

	if(mycode){
        ...
    }else{
        // !!!如果不是微信登录进来的,就会执行这里的代码
        let mytoken = localStorage.getItem("x-auth-token");
        this.chanIsLogined(Boolean(mytoken));
    }

如何进行组件重载?利用key属性

先删除TopBar.vue中的watch。

然后来到App.vue组件,给调用TopBar.vue的地方添加key属性:

<template>	
	...
	<!-- 顶部 -->
    <TopBar :key="topBarKeyValue"></TopBar>
	...
</template>
<script>
    data() {
    return {
      topBarKeyValue:1
    };
  },
	...
    watch: {
    // 监听路由的变化
    "$route.path": {
      handler(newVal, oldVal){
        // console.log(newVal, oldVal)
        if(newVal !== oldVal){
          // key属性的值一变化,就会做组件重载,从而执行created函数
          console.log("组件重载!!!!");
          this.topBarKeyValue++;
        }
      }
    }
  },
</script>	

这样将Application下的token删除之后点击其他路由,将会恢复登录前的状态,而不会一直保持登录后的状态。

三、获取登录用户信息,请求头携带token

3.1、请求头携带token

在登录功能中,目前我们已经完成了保存token到本地存储中。

在真正项目中,只要我们本地存储中有token,在请求的时候都会带上这个token值在每一个请求头中,不管这个请求需不需token,都会带上

接下来,我们就需要在请求拦截器中判断token,携带token:

src/request/request.js中:

instance.interceptors.request.use(config => {
    const token = localStorage.getItem("x-auth-token");
    if (token) {
      // 判断是否存在token,如果存在的话,则每个请求的请求头上都加上token
      config.headers["x-auth-token"] = token; 
    }
    return config
}, err => {
    return Promise.reject(err)
})

3.2、获取用户登录信息

在api.js中:

// 获取登录用户信息
export const UserProfilesAPI = () => request.get("/shop/userProfiles");

在TopBar组件中:

import {UserProfilesAPI} from "@/request/api"
setUserLoginstatus(){
      // 微信登录第二步:临时票据code换取token
      let mycode = this.$route.query.code;
      if (mycode) {  
          ...
      }else{
          // 没有code,说明没有扫码, 或者 用户已经登录了,不用扫码了
          // 判断有没有token,设置登录状态 (因为TopBar上面的信息,是需要靠 有没有登录来去展示的)
          let mytoken = localStorage.getItem("x-auth-token");
          this.chanIsLogined(Boolean(mytoken));
          if(mytoken){
              // 请求并渲染用户信息
              UserProfilesAPI().then(res=>{
                  // 打印用户信息
                  console.log(res);
              });
          }else{
              // 设置回默认的用户信息
          }
      }
},

携带请求头token成功的结果展示:

四、用户信息渲染

但是在项目中,任意组件都可以获取这个用户信息,比如:TopBar.vue,Login.vue等,所以用户信息可以放在vuex中:

store中新建userInfo文件夹,新建index.js

import {UserProfilesAPI} from "@/request/api"

export default {
    namespaced: true,
    state: {
        // 购物车数量
        cartTotal: 0,
        // 用户信息
        userInfo:{
            headImg:require("../../assets/img/userImg.f8bbec5e.png"),
            nickName:"--",
            coin:"--"
        }
    },
    mutations: {
        updateUserInfo(state,payload){
            console.log("payload为:",payload);
            state.cartTotal = payload.cartTotal;
            state.userInfo = payload.userInfo;
        }
    },
    actions: {
        asyncUpdateUserInfo(context){
            UserProfilesAPI().then(res=>{
                // 打印用户信息
                
                context.commit("updateUserInfo",res.data)
            });
        }
    },
}

在TopBar.vue组件中:

<template>
	...
	<li>
        <img
             @click="clickAvatar"
             class="avatar"
             width="26"
             :src="userInfo.headImg"
             alt=""
             />用户名:{{userInfo.nickName}}
    </li>
    <li>我的积分:{{userInfo.coin}}</li>
    <li>获取积分</li>
    <li>叩丁狼官网</li>
    <li class="cart-btn btn" v-show="isLogined">
        <img src="../assets/img/cart.png" alt="" />
        <span>购物车</span>
        <b>{{ cartTotal }}</b>
    </li>
	...
</template>
<script>
setUserLoginstatus(){
    setUserLoginstatus(){
      // 微信登录第二步:临时票据code换取token
      let mycode = this.$route.query.code;
      if (mycode) {  
          // 有code才去换取token
          WeixinLoginApi({
            code: mycode,
          }).then((res) => {
            console.log(res);
            if (res.code === 0) {
              // 登录成功
              // 1、提示用户登录成功
              // 2、保存token值
              // 3、改变登录状态
              // 4、清除浏览器地址栏上的code
              // 5、获取登录用户信息
              this.asyncUpdateUserInfo();

            }else{
              this.asyncChanToastState({
                msg:res.message,
                type:"danger"
              });
            }
          })
      }else{
        // 如果没有code,需要更新用户登录状态

        // 没有code说明,用户没扫码
        // 说明用户已经登录的不用扫码,或者用户没有登录没扫码,
        // 判断用户能否拿到token来做出登录状态的更新
        let mytoken = localStorage.getItem("x-auth-token");
        this.chanIsLogined(Boolean(mytoken));
        // 获取登录用户信息
        if(mytoken){
            this.asyncUpdateUserInfo();
        }
      }
    },
}
</script>

4.1、获取vuex中的图片img

vuex中的图片获取格式 :src="xx",不加{{}}

可能出现图片获取不到的情况===》require("@/assets/img/userImg.f8bbec5e.png")即可!

 在Login.vue组件中登录成功也是异步更新用户信息:

import { mapMutations,mapActions } from "vuex";
...
	...mapActions({
      asyncUpdateUserInfo:"userInfo/asyncUpdateUserInfo"
    }),
	toLogin() {
      // 1&&2、前两个验证已经完成
      // 3 判断验证码是否为空
      // 去做登录
      LoginAPI({
       ...
      }).then((res) => {
        console.log(res);
        if(res.code==0){
            // 1、提示登录成功
            // 2、保存token值,本地存储
            // 3、隐藏登录框
            // 【!!】4登录状态的切换
            // 5、更新用户信息
            this.asyncUpdateUserInfo();
        }
      });
    },

注:如果此时用户头像没有出来,在public文件夹中的index.html文件的head标签里,添加这个标签即可

<!-- 防止服务器检查防盗用链接 -->
<meta name="referrer" content="no-referrer" />

五、删除token后的用户信息初始化

在删除token后,切换路由的时候,用户信息需要还原为默认值

TopBar.vue中以及对应的vuex中:

setUserLoginState() { 
    if(mycode){
        ...
    }else {
        ...
          if (mytoken) {
            ...
          } else {
            // 初始化用户数据
            this.initUserInfo();
          }
     }
 mutations: {
       ......
        // 初始化操作
        initUserInfo(state) {
            // 购物车数量
            state.cartTotal = 0,
                // 用户信息
                state.userInfo = {
                    nickName: "游客~~",
                    coin: 0,
                    headImg: require("@/assets/img/userImg.f8bbec5e.png")
                }
        }
    },

六、首页布局的套用

在实际工作项目中,有可能项目部分代码并不是你完成的,而是你同事完成的。甚至有可能你进入到公司之后,接手你同事的项目,这时候就要求你看得懂别人写的代码。

接下来我们套用首页的结构和样式,将views中的Home.vue和components中的home文件夹替换掉项目原本的文件,然后在其基础上进行数据渲染。

6.1、正向传值+数据最大长度控制的第一种方法

api.js中:

// 首页精品推荐请求
export const JingpinAPI = () => request.get("/products/recommend");
// 请求热门兑换的数据
export const RemenAPI = () => request.get("/products/hot");

src/views/Home.vue中:

备注:jingpinArr和remenArr是data中要去渲染页面的数组,接收请求的数据。

async created() {
   // 精品请求
    let res1 = await JingpinAPI();
    // 过滤出前4项
    if (res1.code == 0) {
        this.jingpinArr = res1.data.data.records.filter(
            (item, index) => index < 4
        );
    }
    // 热门请求
    let res2 = await RemenAPI();
    if (res2.code == 0) {
        this.remenArr = res2.data.data.records.filter((item, index) => index < 6);
    };
    console.log(this.jingpinArr,this.remenArr);
},

src/components/home/List.vue中:

备注:v-for循环中图片的渲染格式 :src="item.xxx",不加{{}}

<li v-for="item in arr" :key="item.id">
    <section>
        <img :src="imgBaseUrl + item.coverImg" alt="" />
        <div class="bottom-box">
            <h3>{{ item.name }}</h3>
            <p>{{ item.coin }}积分</p>
            <div class="btn">立即兑换</div>
        </div>
        <img
             class="flag"
             v-show="item.isLatest == 1"
             src="../../assets/img/section_new.png"
             alt=""
             />
        <img
             class="flag"
             v-show="item.isHotSale == 1"
             src="../../assets/img/section_hot.png"
             alt=""
             />
    </section>
</li>

main.js中保存这个基本图片的url:

// 在组件内部获取这个变量
// 像一个 “全局变量”, 在任意的组件中都可以通过  this.变量名 或者 {{变量名}} 来获取
// 但是不是像Vuex那样共享数据,而是仅仅只是在组件内部的一个变量
Vue.prototype.imgBaseUrl = "http://sc.wolfcode.cn";

6.2、正向传值+数据最大长度控制的第二种方法

备注:左边为子组件,右边为父组件,通过props:["xxx"]接收

备注: 不想使用过滤的话,可以借助maxLength属性和v-show指令对数组最大展示长度进行控制

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值