tab动画 vue_vue 简单实现 cnode社区

介绍

cnode社区是一个中文的nodeJs社区:CNode:Node.js专业中文社区

0576220052917487cd0eed80ccacd7bf.png

实现思路

页面基本结构

头部、中间的列表、侧边栏、文章详情页、用户个人信息、分页

a52f5d2cbe7ebe60595cee846fa76e34.png

46658b74427e35caea5e8bc76166bdac.png

4994723f01d0563d26da5e18c6ae9867.png

然后每个部分用组件渲染

组件模块

  • Header 头部模块
  • PostList 文章、帖子列表模块
  • Article 文章详情模块
  • SliderBar 侧边栏模块
  • UserInfo 用户个人中心模块
  • Pagination 分页模块

技术实现思路

使用 vue2 来开发,涉及到:

  • 计算属性
  • 内置指令和事件绑定
  • 自定义事件和触发
  • 路由跳转、监听
  • 组件通信
  • axios 获取接口

项目搭建

使用vue 脚手架搭建

// vue 脚手架搭建
vue init webpack cnode
// 使用 npm
npm run dev
npm run build

fa1d869069cf59cd7a5577663bb85117.png

npm run dev 开启预览、删掉 helloworld 组件,开始开发

Header 组件

代码仓库:kongyi5/cnode

这个部分简单实现了样式,搜索框也省了

PostList 组件

这部分比较复杂,使用了加载动画、axios获取接口,使用过滤器等等。

一:官方接口:https://cnodejs.org/api/v1/topics;

a9593eba88536809f0d65dcac8fd8f37.png
  • topics 是获取帖子列表,有两个参数,page显示页面内容、limit显示帖子数量;
  • 头像:author.avatar_url
  • 回复量/浏览量:reply_count / visit_count
  • 帖子标题:title
  • 时间:last_reply_at
  • 帖子分类:top(是否置顶)、good(精华帖)、tab(除了置顶、精华外的其余帖子);share(分享)、ask(问答)、job(招聘)

发帖时间过滤:

Vue.filter('formatDate', function (str) {
    if (!str) return ''
    var date = new Date(str)
    var time = new Date().getTime() - date.getTime() //现在的时间-传入的时间 = 相差的时间(单位 = 毫秒)
    if (time < 0) {
      return ''
    } else if ((time / 1000 < 30)) {
      return '刚刚'
    } else if (time / 1000 < 60) {
      return parseInt((time / 1000)) + '秒前'
    } else if ((time / 60000) < 60) {
      return parseInt((time / 60000)) + '分钟前'
    } else if ((time / 3600000) < 24) {
      return parseInt(time / 3600000) + '小时前'
    } else if ((time / 86400000) < 31) {
      return parseInt(time / 86400000) + '天前'
    } else if ((time / 2592000000) < 12) {
      return parseInt(time / 2592000000) + '月前'
    } else {
      return parseInt(time / 31536000000) + '年前'
    }
  }
)

帖子分类过滤:

//处理显示板块的文字
Vue.filter('tabFormatter',function (post) {
  if(post.good == true){
    return '精华'
  }else if(post.top == true){
    return '置顶'
  }else if(post.tab == 'ask'){
    return '问答'
  }else if(post.tab == 'share'){
    return '分享'
  }else{
    return '招聘'
  }
})

Article 组件

这一部分使用了路由作为跳转,然后获取接口的帖子id,在点击帖子的时候把用户名和帖子id在路由里获取好然后传出去

this.$http.get(`https://cnodejs.org/api/v1/topic/${this.$route.params.id}`)

export default new Router({
  routes: [
    {
      name:'post_content',
      path:'/topic/:id&author=:name',
      components:{
        main:Article,
      }
    }
  ]
})

<router-link :to="{
  name:'user_info',
  params:{
  name:reply.author.loginname
  }
  }">
  <span>{{reply.author.loginname}}</span>
</router-link>

SlideBar 组件

还是使用路由渲染,但是是渲染两个组件,点击帖子时同时渲染 Article 和 SlideBar;

使用计算属性获取自定义信息数据:

computed: {
    topcilimitby5() {
        if (this.userinfo.recent_topics) {
          return this.userinfo.recent_topics.slice(0, 5);
        }
      },
      replylimitby5() {
        if (this.userinfo.recent_replies) {
          return this.userinfo.recent_replies.slice(0, 5);
        }
      }
  },

检测路由变化的时候跳转:

watch: {
  '$route' (to, from) {
    this.getArticleData()
  }
}

由于组件会进行复用,而请求data的初始化代码都是放在beforemount中.组件复用,这个方法永远只会执行一次,所有getdata也不会触发,因此把getData放在:

watch: {
  '$route' (to, from) {
  // 对路由变化作出响应...
  console.log('变化了');
  }
}

当路由变化就触发getdata,更新视图

UserInfo 组件

使用路由跳转、获取用户名然后渲染进 Article 和 SliderBar

 {
    name:'user_info',
    path:'/userinfo/:name',
    components:{
      main:UserInfo
    }
  }

this.$http.get(`https://cnodejs.org/api/v1/user/${this.$route.params.name}`)

Pagination 组件

点击按钮显示上一页、下一页、首页、省略

// Pagination
<button v-if="jduge" class="pagebtn">......</button>
<button v-for="btn in pagebtns"
          @click="changeBtn(btn)"
  :class="[{currentPage:btn == currentPage},'pagebtn']">
    {{btn}}
</button>

import $ from 'jquery'
changeBtn(page) {
   //点击上一页,下一页,首页
   if (typeof page != 'number') {
     switch (page.target.innerText) {
       case '上一页':
         $('button.currentPage').prev().click();
         break;
       case '下一页':
         $('button.currentPage').next().click();
         break;
       case '首页':
         this.pagebtns = [1, 2, 3, 4, 5, '......'];
         this.changeBtn(1);
         break;
       default:
         break;
     }
     return;
   }
   this.currentPage = page;
   if (page > 4) {
     this.jduge = true;
   } else {
     this.jduge = false;
   }
   if (page == this.pagebtns[4]) {
     this.pagebtns.shift(); //移除第一个元素
     this.pagebtns.splice(4, 0, this.pagebtns[3] + 1); //添加最后一个
   } else if (page == this.pagebtns[0] && page != 1) {
     //先在第一个位置加一个
     this.pagebtns.unshift(this.pagebtns[0] - 1);
     //移除最后一个数字
     this.pagebtns.splice(5, 1);
   }
  // 分页组件通信
   this.$emit('handleList', this.currentPage);
 }
}

使用父子组件通信,跟随按钮切换分页

// PostList
<!--分页-->
<pagination @handleList="renderList"></pagination>

import pagination from './Pagination'

data(){
  return {
    postPage: 1
  }
}

getData() {
    this.$http.get('https://cnodejs.org/api/v1/topics', {
      params: {
        page: this.postpage,
        limit: 20
      }
    })
    .then(res => ...)

renderList(value) {
  this.postpage = value;
  this.getData();
}

部署到 gitee/github Pages

847572f6762025ab4eeef46722047e4f.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值