一.项目介绍
1.首页(vant tab栏 无限加载 轻提示..)
2.个人面板,编辑,关注,收藏等系列..(信息资料编辑,修改头像,vant 轻提示 选择器 )
3.登录/注册页 (正则表达式,token)
4.新闻详情,评论 (回复) (动态关注点赞,组件递归)
二.项目总结
三.项目展示
( 由于修改头像 网速有限 时间太长 所以不展示 )
3.1 项目路由配置
import Vue from "vue";import VueRouter from "vue-router";import Home from "../views/Home.vue";import Login from "../views/Login.vue";import Register from "../views/Register.vue";import personIndex from "../views/person/Index.vue";import personExit from "../views/person/Exit.vue";import particulars from "../views/Particulars.vue";import attention from "../views/person/attention.vue";import follow from "../views/person/follow.vue";import collect from "../views/person/collect.vue";Vue.use(VueRouter);const routes = [ { path: "/", name: "Home", component: Home }, // 登录 { path: "/login", component: Login }, // 注册 { path: "/register", component: Register }, // 个人中心 { path: "/person", component: personIndex }
.....
];3.2 全局守卫 请求拦截 响应拦截
//全局前置守卫router.beforeEach((to, from, next) => { // 禁止匿名进入的数组 const guardArr = ["/person",'/personExit','/particulars"',"/attention","/follow","/collect"]; const token = localStorage.getItem("token"); if (guardArr.indexOf(to.path) > -1) { if (!token) { router.push({ //如果匿名进入其他守卫数组页面 则进入登录页面 path: "/login" }); } } next();});
//请求拦截axios.interceptors.request.use(req => { if (localStorage.getItem("token")) { // 有token的话,自动带上Authorization req.headers.Authorization = localStorage.getItem("token"); } return req;});//响应拦截axios.interceptors.response.use(req => { const { statusCode } = req.data; // 检测4开头的错误正则表达式 const fourErrRegExp = /^4\d\d/; if (fourErrRegExp.test(statusCode)) { localStorage.removeItem("token"); localStorage.removeItem("user_id"); router.push({ path: "/" }); } return req;});四.项目难点
4.1.1主页tab栏
首先是导入vant-ui 的 Tab 标签页
此为初始的代码
<van-tabs v-model="active">
<van-tab title="标签 1">内容 1</van-tab>
<van-tab title="标签 2">内容 2</van-tab>
<van-tab title="标签 3">内容 3</van-tab>
<van-tab title="标签 4">内容 4</van-tab>
</van-tabs>
注意: van-list 是嵌套在 循环的van-tab 里面的
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<van-cell v-for="item in list" :key="item" :title="item" />
</van-list>修改后的效果:
<div class="home_nav" v-if="articleLists"> <!-- tab栏 --> <van-tabs v-model="activeIndex" color="#31c37b"> <van-tab :title="item.name" v-for="(item,index) of articleLists " :key="index"> <!-- 列表 --> <van-list :immediate-check="false" v-model="item.loading" :finished="item.finished" finished-text="没有更多了" @load="onLoad" > <newBar :v-if="Postitem.length >= 1" :postList="Postitem" v-for="(Postitem,index) of item.content" :key="index" @go_particulars="go_particulars" ></newBar> </van-list> <!-- 列表 --> </van-tab> </van-tabs> <!-- tab栏 --> </div>4.1.2
首先说一说这里踩的坑 因为没有初始化修改tab栏的数据 导致每次切换栏目都会重新发送请求
进入正题:
给每一个tab 的索引 增加一些我们需要的数据 ( 防止切换栏目时 导致频繁发送异步请求 )
( 当数据存在时 则不发送请求 不存在则发送 如果下刷到底部 则触发加载函数 接受的数据后添加到原来的数据上面 )
// 初始化数据 initCategory(data = []) { data.forEach(item => { item.content = []; item.loading = false; //加载显示 item.finished = false; //到底显示 item.pageIndex = 1; //当前tab下的数据的页数 用于后添加数据 每次++ item.pageSize = 10; //每次加载的数据条 bar item.total = 1; // 初始化文章数量 后面获取请求后会重置 }); return data; }, // ? 异步获取post数据 getCategory() { this.$axios({ url: "/category", method: "get" }).then(res => { const { data } = res.data; this.articleLists = this.initCategory(data); // ! 这里调用初始化数据函数 // 获取文章列表 this.getPost(); // 在调用获取文章列表函数 }); }, // ? 获取文章列表 getPost() { const item = this.articleLists[this.activeIndex]; // 获取当前tab栏下的item this.$axios({ method: "get", url: "post", params: { category: item.id, pageIndex: item.pageIndex, pageSize: 10 } }).then(res => { const { data, total } = res.data; // 获取数据 和 total // tatal 是文章一共有多少篇 修改init时默认值1 item.total = total; // 判断是否有数据 if (item.content.length < 1) { item.content = data; } else { item.content = [...item.content, ...data]; } item.pageIndex++; }); }, // 列表加载 onLoad() { const item = this.articleLists[this.activeIndex]; item.loading = true; // 定时器 延迟逼真用户体验 setTimeout( function() { // 一共有的文章数量 / 每次刷新的页数(10) 和 当前页 判断 if (item.total / 10 >= item.pageIndex) { this.getPost(); item.loading = false; } else { item.finished = true; } }.bind(this), 100 ); },4.2.1 组件递归
首先附上图片 带头像的是 母组件 里面嵌套着 带边框的 子组件
后台传来的数据是
[
{
数据..
parent:{数据} //需递归},
{
数据.. // 不需递归
}
]首先循环遍历母组件
<commentSon v-if="comment_item.parent" :parent="comment_item.parent"
@reply="reply_son"></commentSon>
// v-if 判断是否需要递归 @reoly 接受递归组件传来的回复id母组件 methods 函数
reply() { // 子传父 this.$emit("reply", this.comment_item.id); }, reply_son(id) { // 接受递归组件的 子传父 而后 再 子传父 this.$emit("reply", id); }递归组件 首先是html
<template> <div> <!-- 判断是否需要递归 --> <parent v-if="parent.parent" :parent="parent.parent" @reply="reply_digui"></parent> <div class="comment_son"> <span> <i>@{{parent.user.nickname}}</i> : </span> <!-- 点击回复 传id 子传父 --> <p @click="reply(parent.id)" >{{parent.content}}</p> </div> </div></template>递归组件最外层 以及 递归的组件 时 回复的函数
props: ["parent"], // 递归时 接受的parent name: "parent", // 递归组件的前提 methods: { reply() { // 最外层被点击 直接发送给父组件 this.$emit("reply", this.parent.id); }, // 递归组件点击时执行的函数 在递归组件<parent @reply="reply_digui" .. 时绑定了事件 reply_digui(id) { this.$emit("reply", id); } }秭归踩的坑
一开始写html页面的时候 把 @reply="reply_digui" 写错位置 导致递归到最后传出去的id
是最外层的id
<template> <div @reply="reply_digui"> // 这里!! <!-- 判断是否需要递归 --> <parent v-if="parent.parent" :parent="parent.parent"></parent> </div></template>修改后 <template> <div> <!-- 判断是否需要递归 --> <parent v-if="parent.parent" :parent="parent.parent" @reply="reply_digui"></parent>
</div></template>五.结尾
1.申明 : 此项目以及文章仅为本人用于 ( 毕业设计用 ) ( 即将毕业的苦逼学生党 )
2. 如有不足之处或者其他问题的,请各位小哥哥小姐姐指明一下!! thanks~.
3.由于文章长度问题,所以只介绍了项目以及项目难度,后续会根据情况而看是否发送后续补充
我的📪邮箱地址: vscript13169043264@163.com