实现效果
1.首先tab切换实现上面tab功能,用二级路由来实现。
2.根据路由的切换来渲染不同的数据到相同的模板中
tab切换
首先得配置路由,使得进入个人空间时展示默认组件,这里使用到路由重定向,然后配置二级路由,可以在tab切换时变换不同组件:
{
path:'/space',
name:"space",
title:'个人空间',
component:Space,
redirect:{
name:'works'
},
meta:{
login:true
},
children: [
{
path: 'works',
name: 'works',
title: '作品',
component: MenuList,
meta: {
login: true
},
},
{
path: 'fans',
name: 'fans',
title: '我的粉丝',
component: Fans,
meta: {
login: true
},
},
{
path: 'following',
name: 'following',
title: '我的关注',
component: Fans,
meta: {
login: true
},
},
{
path: 'collection',
name: 'collection',
title: '收藏',
component: MenuList,
meta: {
login: true
},
}
]
}
此时展示默认组件是我的作品组件
因为需要在页面加载时初始化一些数据,因此需要使用到watch属性来监听路由的变化,第一个观察自己还是他人空间,第二个加载默认二级路由组件
watch:{
// 监听路由变化,来判断路由是否有信息,从而分辨是否为自己的空间
$route:{
async handler(){
// 来判断路由是否有信息
let {userId} = this.$route.query;
this.isOwner = !userId || userId === this.$store.state.userInfo.userId;
if(this.isOwner){ //当前登录的用户
this.userInfo = this.$store.state.userInfo;
}else{
const {data} = await userInfo({userId});
this.userInfo = data;
}
// console.log(this.userInfo);
// 可以留存上一次tab的访问信息 (视需求而定)
this.activeName = this.$route.name;
// console.log(this.activeName);
this.getInfo();// 请求二级路由的数据
},
immediate:true
}
这里我们采取element-ui来实现具体的tab切换,利用v-model获取切换的值,再来根据路由切换二级组件,
<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>
这里的点击事件是为了将名字和路由结合,用到了编程式导航,我们进入别人空间这样操作的时候,会将userId覆盖掉,根据之前的逻辑,这样会导致跳入自己的空间,因此在编程式导航中还需要将query参数一起放入
tabClickHandler(){
//问题:因为路由二级接收字段,全是info,所以会造成数据重复;
//解决:第一次保存数据到数组时,没有问题,所以每次保存前,都要清空数组
this.list = [];
this.$router.push({
name:this.activeName,
query:{
...this.$route.query
}
});
}
接下来就是模块的展示,根据进入的路由的不同,切换到不同的组件之内,请求不同的数据,渲染模板,
这一块定义在实例之外,目的是简化逻辑处理,可以根据不同的需求来请求不同的数据
const getOtherInfo = {
async works(params){ //作品
let data = (await getMenus(params)).data;
data.flag = 'works';
return data;
},
async following(params){ //关注
let data = (await following(params)).data;
data.flag = 'following';
return data;
},
async fans(params){ //粉丝
let data = (await fans(params)).data;
data.flag = 'fans';
return data;
},
async collection(params){ //收藏
let data = (await collection(params)).data;
data.flag = 'collection';
return data;
}
}
这里就是数据请求模块,根据tab的切换值来请求上面不同的数据,从而渲染不同模块,这里的调用实在watch中执行
async getInfo(){
let data = await getOtherInfo[this.activeName]({userId:this.userInfo.userId});
//问题二:切换tab过快时,依然报错key重复,并切数据显示不正常
//原因:因为ajax返回数据 返回时间快慢的问题,显示的事最后一次ajax的返回的数据
//解决:在请求定义一个标识,在返回的数据添加标识
if(this.activeName === data.flag){
this.list = data.list;
}
}
在粉丝模块中接收参数,info是数据,activeName是名称
export default {
props:{
info:{
type:Array,
default:()=>[]
},
activeName:{
type:String,
default:'fans'
}
}
}
在粉丝在粉丝模块中渲染数据
<ul class="fans clearfix">
<router-link
v-for="item in info"
:key="item.userId"
:to="{name:'space',query:{userId:item.userId}}"
tag="li" >
<a href="javascript:;" class="img">
<img :src="item.avatar"></a>
<div class="c">
<strong class="name">
<router-link :to="{name:'space',query:{userId:item.userId}}">{{item.name}}</router-link>
</strong>
<em class="info"><span>粉丝:</span> {{item.follows_len}} | <span>关注:</span>{{item.following_len}}</em>
<em class="info">
<span>简介:{{item.sign}}</span>
<!-- 这个人太懒啦!还没有介绍自己 -->
</em>
</div>
</router-link>
</ul>
同理,在其他的也一样