效果图
router文件下的index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import Home from '@/views/home/Home.vue'
const login = () => import( '../views/user-login/index.vue' );
const detail = () => import( '../views/detail/detail.vue' );
const space = () => import( '../views/user-space/space.vue' );
const fans = () => import( '../views/user-space/fans.vue' );
const MenuList = () => import( '../views/user-space/menu-list.vue' );
import { userInfo } from '@/service/api';
import Store from '@/store'
// import { Store } from "vuex"
const router = new Router({
mode: "history",
routes: [{
path: '/',
name: "Home",
title: '首页',
component: Home
},
{
path: '/login',
name: "login",
title: '登录页',
component: login,
},
{
path: '/detail',
name: "detail",
title: '',
component: detail,
meta: {
login: true
}
},
//个人空间的路由信息
{
path: '/space',
name: "space",
title: '个人空间',
component: space,
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
}
},
]
}]
});
// var islogin = true
// var isLogin = true; // 是否登录
//
// redirect:{
// name:"works"
// },
router.beforeEach(async (to, from, next) => {
// 进入路由守卫时,向后端发送 token,验证是否合法 mes
let data = await userInfo();
Store.commit("chnageUserInfo", data.data);
// this.$store.commit("chnageUserInfo",data.data);
if (to.matched.some(item => item.meta.login)) { //判断一下是否需要登录
// console.log("需要登录");
const token = localStorage.getItem("token");
// !!将数据类型转换为布尔值
const isLogin = !!token;
// console.log(isLogin);
// console.log(data);
if (isLogin) {
if (data.error === 400) { // 后端告诉你,token不合法
next({ name: 'login' });
localStorage.removeItem('token');
return;
}
next();
return;
}
// 没登录, 但是要进入登录页
if (!isLogin && to.name === 'login') {
next();
}
// 没登录, 要进入的页面也不是登录
if (!isLogin && to.name !== 'login') {
next({ name: 'login' });
}
} else {
next();
}
})
export default router;
点击进行路由跳转,query里面的是传的用户id
<router-link :to="{ path: '/space' }" >
</router-link>
或
<router-link :to="{ path: '/space', query: { userId: item.userId } }" >
</router-link>
space.vue
<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">
{{ userInfo.createdAt }} <em>加入美食杰</em>
|
<router-link to="" v-show="!isOwner">编辑个人资料</router-link>
</span>
<div class="tools" v-show="!isOwner">
<!-- follow-at no-follow-at {{followUserId?关注:取消关注}}-->
<a
href="javascript:;"
class="follow-at"
:calss="{ '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> -->
<!--:info="list"传的是数据 :activeName="activeName" 二级路由-->
<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) {
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;
},
};
export default {
name: "Space",
data() {
return {
userInfo: {},
isOwner: false,
getMenus: [],
activeName: "works",
list: [],
};
},
watch: {
$route: {
async handler(item) {
// 入则id
let { userId } = item.query;
//先判断是不是空,在判断是不是自己的userId
// deep:true
this.isOwner = !userId || userId === this.$store.state.userInfo.userId;
// console.log(this.isOwner);
if (!userId) {
this.userInfo = this.$store.state.userInfo;
} else {
const data = await userInfo({ userId });
this.userInfo = data.data;
}
this.getInfo();
},
immediate: true,
},
},
methods: {
async getInfo() {
var data = await getOtherInfo[this.activeName]({ userId: this.userInfo.userId });
// 问题二:切换tab过快时,依然报错key重复。并且数据显示不正常
// 原因:因为ajax返回数据 快慢的问题,显示的最后一次ajax返回的数据
// 解决:在请求中定义一个标识,在返回的数据中添加标识,如果返回的数据和当前的标识相同,再渲染
if (this.activeName === data.flag) {
this.list = data.list;
console.log(this.list);
}
},
async toggleHandler() {
await toggleFollowing({ followUserId: this.userInfo.userId }).then((item) => {
//因为关注后,要更新的数据还有粉丝,所以整体赋值数据
this.userInfo = item.data;
});
},
//点击切换tab
tabClickHandler() {
// 问题1:因为各个二级路由接收的手段,全是info ,所有会造成数据重复。
// 解决:第一次保护数据到数组中时,没有问题,所以,每次保存前,都清空一下数组
this.$router.push({
name: this.activeName,
query: {
...this.$route.query,
},
});
},
},
};
</script>
<style lang="stylus">
MenuList
<template>
<div class="menu-list">
<div class="info-empty" v-show="activeName=='works'&&info.length==0" >
<div>
<p>私房菜不要偷偷享用哦~~制作成菜谱与大家分享吧!</p>
<a href="">发布菜单</a>
</div>
</div>
<div class="info-empty" v-show="activeName=='collection'&&info.length==0">
<div>
<p>还没有收藏任何的菜谱,去搜自己喜欢的菜谱,收藏起来吧。</p>
<a href="">菜谱大全</a>
</div>
</div>
<menu-card :margin-left="13" :info="info"></menu-card>
</div>
<!-- -->
</template>
<script>
import MenuCard from "@/components/menu-card.vue";
export default {
components: { MenuCard },
props: {
info: {
type: Array,
default: () => {},
},
activeName:{
type: String,
default:"works",
}
},
};
</script>
fans
<template>
<div class="fans">
<div class="info-empty">
<div>
<p v-show="activeName=='fans'&&info.length==0">还没有被关注哦!多发布菜谱,更容易被找到。</p>
<p v-show="activeName=='following'&&info.length==0">还没有关注别人哦!可以预览菜谱,找到别人</p>
</div>
</div>
<ul class="fans clearfix">
<router-link to="" tag="li" v-for="(item, index) in info" :key="index">
<a href="javascript:;" class="img"> <img :src="item.avatar" /></a>
<div class="c">
<strong class="name">
<router-link
:to="{ path: '/space', query: { userId: item.userId } }"
tag="em"
>{{ item.name }}</router-link
>
</strong>
<em class="info">
<span>粉丝:</span> {{ item.follows_len }} | <span>关注:</span
>{{ item.following_len }}
</em>
<em class="info"><span>简介:</span> {{item.sign? item.sign: "这个人太懒啦!还没有介绍自己"}}</em>
</div>
</router-link>
</ul>
</div>
</template>
如果一直报这个
可以在router文件下的index.js,export default router前面写入
const originalPush = Router.prototype.push
Router.prototype.push = function push (location) {
return originalPush.call(this, location).catch(err => err)
}
export default router;