《美食街》项目(个人空间篇)

内容:个人空间分为‘基础信息’和‘发布、关注、粉丝,收藏这些’。

在这里插入图片描述
代码如下:

<template>
  <div class="space">
    <h2>欢迎来到我的美食空间</h2>
    <div class="user-info">
      <div class="user-avatar">
        <img :src="userInfo.avatar" alt="">
      </div>
      <div class="user-main">
        <h1>{{userInfo.name}}</h1>
        <span class="info">
          <em>{{ userInfo.createdAt
          }}加入美食杰</em>
          |
          <router-link :to="{name:'edit'}" v-if="isOwner">编辑个人资料</router-link>
        </span>
        <div class="tools"  v-if="!isOwner">
          <!-- follow-at  no-follow-at-->
				  <a href="javascript:;" class="follow-at"
          :class="{'no-follow-at':userInfo.isFollowing}"
          @click="toggleHandler"
          >
            {{ userInfo.isFollowing ? "已关注" :"+ 关注"}}
          </a>
        </div>
      </div>
      <ul class="user-more-info">
        <li>
          <div>
            <span>关注</span>
            <strong>{{userInfo.following_len}}</strong>
          </div>
        </li>
        <li>
          <div>
            <span>粉丝</span>
            <strong>{{userInfo.follows_len}}</strong>
          </div>
        </li>
        <li>
          <div>
            <span>收藏</span>
            <strong>{{ userInfo.collections_len }}</strong>
          </div>
        </li>
        <li>
          <div>
            <span>发布菜谱</span>
            <strong>{{ userInfo.work_menus_len }}</strong>
          </div>
        </li>
      </ul>
    </div>
    <!-- v-model="activeName" -->
    <el-tabs class="user-nav" v-model="activeName" @tab-click="tabClickHandler">
      <el-tab-pane label="作品" name="works"></el-tab-pane>
      <el-tab-pane label="粉丝" name="fans"></el-tab-pane>
      <el-tab-pane label="关注" name="following"></el-tab-pane>
      <el-tab-pane label="收藏" name="collection"></el-tab-pane>
    </el-tabs>
    <div class="user-info-show">
      <!-- 作品 & 收藏 布局 -->
      <!-- <menu-card :margin-left="13"></menu-card> -->
      <!-- 粉丝 & 关注 布局 -->
      <!-- <Fans></Fans> -->
      <router-view :info="list" :activeName="activeName"></router-view>
    </div>
  </div>
</template>
<script>
import {userInfo, toggleFollowing, getMenus, following, fans, collection} from '@/service/api';

const getOtherInfo={
  async works(params){//作品
      return (await getMenus(params)).data;
  },
  async fans(params) {//粉丝
    return (await fans(params)).data;
  },
  async following(params) {//关注
    return (await following(params)).data;
  },
  async collection(params) {//收藏
    return (await collection(params)).data;
  }
}
export default {
  name: 'Space',
  data(){
    return {
      userInfo:{},
      isOwner:'',
      activeName:'works',
      list:[],
      queen:{}
    }
  },
  watch:{
    $route:{
      async  handler(){
        let {userId}=this.$route.query
        //如果没有userId,或者userId等于仓库中储存的userId
        this.isOwner=!userId||userId ===this.$store.state.userInfo.userId
        if(this.isOwner){//当前登录用户
          this.userInfo = this.$store.state.userInfo
          console.log(this.userInfo)
        }else{
          const data=await userInfo({userId});
          this.userInfo=data.data
        }
        this.activeName=this.$route.name //留存上一次的访问(例如:上一次访问的是收藏,下一次打开,还在收藏)
        this.getInfo();
      },
      immediate:true
  	 }
  },
  methods:{
    async toggleHandler(){
     const data= await toggleFollowing({followUserId:this.userInfo.userId})
     this.userInfo=data.data
    },
    tabClickHandler(){
      // console.log(this.activeName)
      this.list = []//每次点击,清空数据,防止key 重复

      this.$router.push({
        name:this.activeName,
        query:{//留存query 避免覆盖
          ...this.$route.query
        }
      })
    },
    async getInfo(){
      //问题:如果tab 切换过快,会报错key重复,并且数据也显示不正常
      //原因:因为Ajax返回数据快慢的问题,显示的最后一次Ajax返回的数据,无法下是对应的数据
      //如果接口名不同的情况下,可以用第一种方式,如果相同或者过于繁杂,可以使用本方法
      //原理:使用闭包的形式存储每一次请求的标记,复制时选取当前的标记进行对比,防止混乱(因为请求Ajax需要时间)
      (async (activeName)=>{
      let data=await getOtherInfo[this.activeName]({userId:this.userInfo.userId})
      this.queen[activeName]=data.list;
      //取当前路由的name对应的数据
      console.log(activeName,this.activeName)
      if(activeName===this.activeName){
        this.list=this.queen[this.activeName]
      }
      this.queen={}
      })(this.activeName)
    }
  },
}
</script>

<style lang="stylus">
.space
  h2
    text-align center
    margin 20px 0
  .user-info
    height 210px
    background-color #fff
    display flex
    .user-avatar
      width 210px
      height 210px
      
      img 
        width 100%
        height 100% 
    .user-main
      width 570px
      padding 20px
      position relative
      h1
        font-size 24px
        color #333
        line-height 44px
      .info  
        font-size 12px
        line-height 22px
        color #999
        a
          color #999
      .tools 
        position absolute
        right 20px
        top 20px
        vertical-align top;
        a
          display inline-block
          padding 3px 0
          width 50px
          color #fff
          text-align center
        a.follow-at
          background-color  #ff3232
        a.no-follow-at 
          background-color #999
          
    .user-more-info
      width 190px
      overflow hidden
      padding-top 20px
      li
        width 81px
        height 81px
        border-radius 32px
        border-bottom-right-radius 0
        margin 0px 8px 8px 0px
        float left
        div
          display block
          height 81px
          width 81px
          box-shadow 0px 0px 6px rgba(0,0,0,0.05) inset
          border-radius 32px
          border-bottom-right-radius 0

          span 
            color #999
            line-height 20px
            display block
            padding-left 14px
            padding-top 14px

          strong 
            display block
            font-size 18px
            color #ff3232
            font-family Microsoft Yahei
            padding-left 14px
            line-height 32px

  .user-nav
    margin 20px 0 20px 0
  .user-info-show
    min-height 300px
    background #fff
    padding-top 20px
    .info-empty
      width 100% 
      min-height inherit
      display flex
      align-items center
      justify-content:center;
      p 
        text-align center
        font-size 12px
      a 
        text-align center
        display block
        height 48px
        width 200px
        line-height 48px
        font-size 14px
        background #ff3232
        color #fff
        font-weight bold
        margin 0px auto
  .el-tabs__item.is-active 
    color: #ff3232;
  .el-tabs__active-bar
    background-color: #ff3232;
  .el-tabs__nav-wrap::after
    background-color: transparent;
</style>


步骤:

1.首先获取数据进行渲染,监听路由变化。

监听路由变化,来判断路由是否有userId。
如果有则代表不是自己的空间,则通过api调用后端获取数据。
如果没有数据,则代表自己的空间,获取vuex里的userInfo信息进行渲染。
在data里面创建一个名为userInfo的对象,然后把获取到的数据进行赋值。

 watch:{
    // 监听路由变化,来判断路由是否有信息,从而分辨是否为自己的空间
    $route:{
      async handler(){
        let {userId}=this.$route.query
        //如果没有userId,或者userId等于仓库中储存的userId
        this.isOwner=!userId||userId===this.$store.state.userInfo.userId
        if(this.isOwner){ //当前登录用户
          this.userInfo = this.$store.state.userInfo
          console.log(this.userInfo)
        }else{
          const data=await userInfo({userId});
          this.userInfo=data.data
        }
        this.activeName=this.$route.name //留存上一次的访问(例如:上一次访问的是收藏,下一次打开,还在收藏)
        this.getInfo(); //监听变化则触发该事件
      },
      immediate:true
    }
  },

通过判断isOwner的值来进行对userInfo赋值,和对‘编辑资料’这条信息。
对数据进行渲染

2.因为下面的tab切换需要配置路由,因为作品和收藏的布局基本一样,粉丝和关注的布局基本一样,所以用的是同一个组件。

在js中声明一个:

const getOtherInfo={
  async works(params){//作品
      return (await getMenus(params)).data;
  },
  async fans(params) {//粉丝
    return (await fans(params)).data;
  },
  async following(params) {//关注
    return (await following(params)).data;
  },
  async collection(params) {//收藏
    return (await collection(params)).data;
  }
}

3.给tab切换的地方添加一个点击事件tabClickHandler,让他点击的时候进行路由跳转。因为是使用的element渲染的,所以绑定点击事件需要使用@tab-click

tabClickHandler(){
      this.list = []//每次点击,清空数据,防止key 重复
      this.$router.push({
        name:this.activeName,
        query:{//留存query 避免其它路由覆盖
          ...this.$route.query
        }
      })
    },

4.监听路由时也在监听此方法,(根据上面定义的activeName标志)

async getInfo(){
      //问题:如果tab 切换过快,会报错key重复,并且数据也显示不正常
      //原因:因为Ajax返回数据快慢的问题,显示的最后一次Ajax返回的数据,无法下是对应的数据
      //如果接口名相同或者过于繁杂,可以使用本方法
      //原理:使用闭包的形式存储每一次请求的标记,复制时选取当前的标记进行对比,防止混乱(因为请求Ajax需要时间)
      (async (activeName)=>{
      let data=await getOtherInfo[this.activeName]({userId:this.userInfo.userId})
      this.queen[activeName]=data.list;
      //取当前路由的name对应的数据
      console.log(activeName,this.activeName)
      if(activeName===this.activeName){
        this.list=this.queen[this.activeName]
      }
      this.queen={}
      })(this.activeName)
    }
  },

根据标记取得当前路由数据,然后渲染。

若有疑问,及时提出哦

小作者在努力持续更新中…

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漠媂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值