目录:
内容:个人空间分为‘基础信息’和‘发布、关注、粉丝,收藏这些’。
代码如下:
<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)
}
},
根据标记取得当前路由数据,然后渲染。
若有疑问,及时提出哦
小作者在努力持续更新中…