Vue.js <move>简单的移动端新闻网站

1,808 阅读5分钟
一.项目介绍 

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