感谢那些无私开源的程序员,你们是最可爱的人儿~~~~

//根app app.js
<template>
<div id="app">
<v-header></v-header>
<div class="main">
<router-view></router-view>
</div>
<v-footer></v-footer>
</div>
</template> <script>
import vHeader from './components/header'
import vFooter from './components/footer' export default {
name: 'app',
components: {
vHeader,
vFooter
}
}
</script> <style>
#app {
font-family: Helvetica, Arial, sans-serif;
font-size: 14px;
background: #E2E2E2;
color: #778087;
}
img {
height: auto;
vertical-align: top;
}
.main {
width: 1100px;
margin: 0 auto;
}
</style>

公共header

//src/components/header.vue
<template>
<div class="header">
<div class="header-wrapper">
<h1 class="title">
<router-link to="/tag/all">
<img src="./../assets/logo.png">
<span>cNodeJS</span>
</router-link>
</h1>
<p class="about">关于</p>
</div>
</div>
</template> <script>
export default {
};
</script> <style scoped>
.header {
background: #fff;
margin-bottom: 35px;
}
.header .header-wrapper {
width: 1100px;
margin: 0 auto;
overflow: hidden;
}
.header .header-wrapper .title {
float: left;
padding: 10px 0;
}
.header .header-wrapper .title img {
width: 30px;
height: 30px;
vertical-align: middle;
margin-right: 10px;
}
.header .header-wrapper .title span {
font-size: 18px;
font-weight: bold;
color: #778087;
}
.header .header-wrapper .about {
float: right;
margin-top: 15px;
}
</style>

//src/components/footer.vue
<template>
<div class="footer">
<p>由 Vue 强力驱动 | Write - By XMit</p>
</div>
</template> <script>
export default {
name: 'footer',
}
</script> <style scoped>
.footer {
background: #fff;
margin-top: 35px;
padding: 50px 0 30px;
text-align: center;
}
</style>

路由部分

//src/router/index.js
import Vue from 'vue'
import Router from 'vue-router' import main from '@/components/main';
import detail from '@/components/detail';
import user from '@/components/user'; Vue.use(Router) export default new Router({
routes: [
{
path: '/',
name: 'home',
component: main,
children: [
{
path: '/tag/:id',
}
]
},
{
path: '/topic/:id',
name: 'detail',
component: detail
},
{
path: '/user/:id',
name: 'user',
component: user
},
]
})
//src/components/user.vue
<template>
<div class="user" v-if="user.length !== 0">
<div class="user-info">
<div class="user-info-hd">个人用户信息</div>
<div class="user-info-bd">
<ul>
<li>
<img :src="user.avatar_url" alt="img">
<p class="username">{{user.loginname}}</p>
</li>
<li>{{user.score}} 积分</li>
<li>github <a :href="'http://github.com/' + user.githubUsername">{{'http://github.com/' + user.githubUsername}}</a></li>
<li>注册时间 {{getTime(user.create_at)}}</li>
</ul>
</div>
</div>
<div class="new-topic" v-if="user.recent_topics.length !== 0">
<div class="new-topic-hd">最近创建的话题</div>
<div class="new-topic-bd">
<ul>
<li v-for="item in user.recent_topics">
<img :src="user.avatar_url" alt="img">
<router-link :to="{ name: 'detail', params: {id: item.id} }" class="title">{{item.title}}</router-link>
</li>
</ul>
</div>
</div>
<div class="participate" v-if="user.recent_replies.length !== 0">
<div class="participate-hd">最近参与的话题</div>
<div class="participate-bd">
<ul>
<li v-for="item in user.recent_replies">
<img :src="user.avatar_url" alt="img">
<router-link :to="{ name: 'detail', params: {id: item.id} }" class="title">{{item.title}}</router-link>
</li>
</ul>
</div>
</div>
</div>
</template> <script>
export default {
props: ['userdata'],
data: function() {
return {
user: []
};
},
methods: {
getData: function() {
this.$http
.get("https://cnodejs.org/api/v1/user/" + (this.userdata || this.$route.params.id), {
params: {}
})
.then(it => {
this.user = it.data.data;
console.log(this.user);
})
.catch(it => {
console.log("user.vue:", it);
});
},
getDateTimeStamp: function (dateStr){
return Date.parse(dateStr.replace(/-/gi,"/").replace(/[A-Z]+/gi," "));
},
getTime: function(hisTime, nowTime) {
var now = nowTime ? nowTime : new Date().getTime(),
diffValue = now - this.getDateTimeStamp(hisTime),
result = "",
minute = 1000 * 60,
hour = minute * 60,
day = hour * 24,
halfamonth = day * 15,
month = day * 30,
year = month * 12,
_year = diffValue / year,
_month = diffValue / month,
_week = diffValue / (7 * day),
_day = diffValue / day,
_hour = diffValue / hour,
_min = diffValue / minute;
if (_year >= 1) result = parseInt(_year) + "年前";
else if (_month >= 1) result = parseInt(_month) + "个月前";
else if (_week >= 1) result = parseInt(_week) + "周前";
else if (_day >= 1) result = parseInt(_day) + "天前";
else if (_hour >= 1) result = parseInt(_hour) + "个小时前";
else if (_min >= 1) result = parseInt(_min) + "分钟前";
else result = "刚刚";
return result;
}
},
created() {
this.getData();
}
};
</script> <style scoped>
.user {
border-radius: 4px;
}
.user a {
color: #778087;
}
.user-info,
.new-topic,
.participate {
margin-bottom: 20px;
background: #fff;
border-radius: 4px;
}
.user .user-info-hd,
.new-topic .new-topic-hd,
.participate .participate-hd {
padding: 10px 20px;
background: #F6F6F6;
border-radius: 4px;
}
.user .user-info-bd img {
width: 50px;
height: auto;
border-radius: 4px;
margin-bottom: 5px;
}
.new-topic .new-topic-bd img,
.participate .participate-bd img {
width: 30px;
height: auto;
border-radius: 4px;
margin-bottom: 5px;
margin-right: 10px;
vertical-align: middle;
}
.user .user-info-bd {
padding: 20px;
}
.user .user-info-bd li {
margin-bottom: 10px;
}
.new-topic .new-topic-bd li,
.participate .participate-bd li {
border-bottom: 1px solid #ddd;
padding: 5px 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.new-topic .new-topic-bd li:last-child,
.participate .participate-bd li:last-child {
border-bottom: 0
}
</style>



//src/components/main.vue
<template>
<div class="main">
<div class="main-wrapper">
<ul class="tab-list">
<li class="item" @click="tabs('all')">全部</li>
<li class="item" @click="tabs('good')">精华</li>
<li class="item" @click="tabs('share')">分享</li>
<li class="item" @click="tabs('ask')">问答</li>
<li class="item" @click="tabs('job')">招聘</li>
<li class="item" @click="tabs('dev')">客户端测试</li>
</ul>
<ul class="list">
<li v-for="(item,index) in content" :key="index" class="item">
<div class="item-hd">
<router-link :to="{ name: 'user', params: {id: item.author.loginname} }" class="user">
<img :src="item.author.avatar_url">
</router-link>
</div>
<div class="item-bd">
<router-link :to="{ name: 'detail', params: {id: item.id} }" class="title">{{item.title}}</router-link>
<p class="footer">
<span class="reply" v-show="item.reply_count !== 0">{{item.reply_count}}</span>
<span class="authour">{{item.author.loginname}} • </span>
<span class="time">创建于: {{getTime(item.create_at)}}</span>
</p>
<p :class="{top: item.top}" v-if="item.top">置顶</p>
</div>
</li>
</ul>
</div>
<p class="pagination">
<!-- <a class="button" @click="prev" >GO PREV</a>
<a class="button" @click="next" >GO NEXT</a> -->
<v-tab v-on:changePage="test"></v-tab>
</p>
</div>
</template> <script>
import vTab from "./tab"; export default {
data: function() {
return {
content: [],
page: 1,
tab: 'all',
show: true
};
},
methods: {
test(page) {
// console.log('page:' + page)
this.page = page
},
tabs(data) {
this.tab = data
this.$router.push({ path: `/tag/${data}` })
},
prev() {
if(this.page > 1) {
return this.page--
}
},
next() {
return this.page++
},
getData: function(page,tab) {
this.$http
.get("https://cnodejs.org/api/v1/topics", {
params: {
page: page,
limit: 0,
tab: tab,
mdrender: true
}
})
.then(it => {
this.content = it.data.data
})
.catch(it => {
console.log("main.vue:", it);
});
},
getDateTimeStamp: function (dateStr){
return Date.parse(dateStr.replace(/-/gi,"/").replace(/[A-Z]+/gi," "));
},
getTime: function(hisTime, nowTime) {
var now = nowTime ? nowTime : new Date().getTime(),
diffValue = now - this.getDateTimeStamp(hisTime),
result = "",
minute = 1000 * 60,
hour = minute * 60,
day = hour * 24,
halfamonth = day * 15,
month = day * 30,
year = month * 12,
_year = diffValue / year,
_month = diffValue / month,
_week = diffValue / (7 * day),
_day = diffValue / day,
_hour = diffValue / hour,
_min = diffValue / minute;
if (_year >= 1) result = parseInt(_year) + "年前";
else if (_month >= 1) result = parseInt(_month) + "个月前";
else if (_week >= 1) result = parseInt(_week) + "周前";
else if (_day >= 1) result = parseInt(_day) + "天前";
else if (_hour >= 1) result = parseInt(_hour) + "个小时前";
else if (_min >= 1) result = parseInt(_min) + "分钟前";
else result = "刚刚";
return result;
}
},
created() {
this.getData(this.page)
},
watch: {
page(val) {
this.getData(val)
},
tab(newVal, oldVal) {
this.getData(this.page, newVal)
},
$route(to, from) {
// this.getData(to.params.id)
this.getData(this.page, to.params.id)
}
},
components: {
vTab
}
};
</script> <style scoped>
.tab-list {
overflow: hidden;
padding: 10px 15px;
background: #f6f6f6;
border-radius: 4px 4px 0 0;
}
.tab-list .item {
float: left;
margin-right: 15px;
}
.button {
display: inline-block;
background: #212121;
color: #fff;
font-weight: bold;
text-align: center;
padding: 1em;
cursor: pointer;
text-decoration: none;
}
.pagination {
padding: 20px 0 0;
text-align: center;
}
.main .main-wrapper {
background: #fff;
border-radius: 4px;
}
.main .main-wrapper .list .item {
overflow: hidden;
padding: 10px;
border-bottom: 1px solid #ddd;
}
.main .main-wrapper .list .item:last-child {
border: 0;
}
.main .main-wrapper .list .item .item-hd {
float: left;
}
.main .main-wrapper .list .item .item-hd .user {
display: inline-block;
}
.main .main-wrapper .list .item .item-hd img {
width: 50px;
height: 50px;
display: inline-block;
border-radius: 4px;
}
.main .main-wrapper .list .item .item-bd {
margin-left: 70px;
}
.main .main-wrapper .list .item .item-bd .title {
font-size: 16px;
margin-bottom: 5px;
color: #778087;
}
.main .main-wrapper .list .item .item-bd .footer {
color: #8492a6;
}
.main .main-wrapper .list .item .item-bd .footer .reply {
display: inline-block;
position: absolute;
right: 10px;
top: 15px;
background: #aab0c5;
border-radius: 10px;
width: 30px;
text-align: center;
color: #fff;
font-size: 12px;
}
.main .main-wrapper .list .item .item-bd {
position: relative;
}
.main .main-wrapper .list .item .item-bd .top {
position: absolute;
right: -20px;
top: -20px;
background: #81bb24;
color: #fff;
padding: 3px 3px;
border-radius: 2px;
font-size: 12px;
text-indent: -9999px;
transform: rotate(-45deg);
}
</style>

//src/components/detail.vue
<template>
<div class="content" v-if="itemdetail">
<div class="detail-left">
<div class="detail">
<div class="detail-wrapper">
<div class="detail-hd">
<h2 class="title">{{itemdetail.title}}</h2>
<span class="time">发布于 {{getTime(itemdetail.create_at)}} •</span>
<span class="author">作者 {{itemdetail.author.loginname}} •</span>
<span class="visit">{{itemdetail.visit_count}} 次浏览</span>
</div>
<div class="detail-bd">
<div id="content" v-html="itemdetail.content"></div>
</div>
</div>
</div>
<v-reply :replydata="itemdetail.replies"></v-reply>
</div>
<div class="detail-right">
<v-user :userdata="itemdetail.author.loginname"></v-user>
</div>
</div>
</template> <script>
import vReply from "./reply";
import vUser from "./user"; export default {
name: "detail",
data() {
return {
itemdetail: ""
};
},
methods: {
getData: function(id) {
this.$http
.get("https://cnodejs.org/api/v1/topic/" + id, {
params: {
accesstoken: true,
mdrender: true
}
})
.then(it => {
this.itemdetail = it.data.data;
// console.log(this.itemdetail);
})
.catch(it => {
// console.log('detail.vue:',it)
});
},
getDateTimeStamp: function (dateStr){
return Date.parse(dateStr.replace(/-/gi,"/").replace(/[A-Z]+/gi," "));
},
getTime: function(hisTime, nowTime) {
var now = nowTime ? nowTime : new Date().getTime(),
diffValue = now - this.getDateTimeStamp(hisTime),
result = "",
minute = 1000 * 60,
hour = minute * 60,
day = hour * 24,
halfamonth = day * 15,
month = day * 30,
year = month * 12,
_year = diffValue / year,
_month = diffValue / month,
_week = diffValue / (7 * day),
_day = diffValue / day,
_hour = diffValue / hour,
_min = diffValue / minute;
if (_year >= 1) result = parseInt(_year) + "年前";
else if (_month >= 1) result = parseInt(_month) + "个月前";
else if (_week >= 1) result = parseInt(_week) + "周前";
else if (_day >= 1) result = parseInt(_day) + "天前";
else if (_hour >= 1) result = parseInt(_hour) + "个小时前";
else if (_min >= 1) result = parseInt(_min) + "分钟前";
else result = "刚刚";
return result;
}
},
created() {
this.getData(this.$route.params.id);
},
watch: {
$route(to, from) {
this.getData(to.params.id)
// console.log(to, from)
}
},
components: {
vReply,
vUser
}
};
</script> <style scoped>
.content {
overflow: hidden;
}
.detail-left {
float: left;
width: 70%;
}
.detail-right {
float: right;
width: 28%;
}
.detail .detail-wrapper {
background: #fff;
border-radius: 4px;
}
.detail .detail-wrapper .detail-hd,
.detail .detail-wrapper .detail-bd {
padding: 20px;
}
.detail .detail-wrapper .detail-hd {
border-bottom: 1px solid #ddd;
}
.detail .detail-wrapper .detail-hd .title {
font-size: 20px;
margin-bottom: 15px;
}
</style>

//src/components/reply.vue
<template>
<div class="reply" v-if="replydata && replydata.length !== 0">
<div class="reply-wrapper">
<p class="reply-head">{{replydata.length}} 回复</p>
<ul class="list">
<li class="item" v-for="(item, index) in replydata" :key="index">
<div class="item-hd">
<router-link :to="{ name: 'user', params: {id: item.author.loginname} }" class="user">
<img :src="item.author.avatar_url">
</router-link>
</div>
<div class="item-bd">
<div class="top">
<span class="user">{{item.author.loginname}}</span>
<span class="floor">{{index+1}} 楼</span>
<span class="time">{{getTime(item.create_at)}}</span>
</div>
<div class="content" v-html="item.content"></div>
</div>
</li>
</ul>
</div>
</div>
</template> <script>
export default {
name: "reply",
props: ["replydata"],
methods: {
getDateTimeStamp: function (dateStr){
return Date.parse(dateStr.replace(/-/gi,"/").replace(/[A-Z]+/gi," "));
},
getTime: function(hisTime, nowTime) {
var now = nowTime ? nowTime : new Date().getTime(),
diffValue = now - this.getDateTimeStamp(hisTime),
result = "",
minute = 1000 * 60,
hour = minute * 60,
day = hour * 24,
halfamonth = day * 15,
month = day * 30,
year = month * 12,
_year = diffValue / year,
_month = diffValue / month,
_week = diffValue / (7 * day),
_day = diffValue / day,
_hour = diffValue / hour,
_min = diffValue / minute;
if (_year >= 1) result = parseInt(_year) + "年前";
else if (_month >= 1) result = parseInt(_month) + "个月前";
else if (_week >= 1) result = parseInt(_week) + "周前";
else if (_day >= 1) result = parseInt(_day) + "天前";
else if (_hour >= 1) result = parseInt(_hour) + "个小时前";
else if (_min >= 1) result = parseInt(_min) + "分钟前";
else result = "刚刚";
return result;
}
}
};
</script> <style scoped>
.reply {
margin-top: 30px;
background: #fff;
border-radius: 4px;
}
.reply .reply-wrapper .reply-head {
padding: 8px 10px;
background: #f6f6f6;
border-radius: 4px;
}
.reply .reply-wrapper .list .item {
overflow: hidden;
padding: 20px;
border-bottom: 1px solid #ddd;
}
.reply .reply-wrapper .list .item:last-child {
border: 0;
}
.reply .reply-wrapper .list .item .item-hd {
float: left;
}
.reply .reply-wrapper .list .item .item-hd img {
border-radius: 4px;
width: 50px;
}
.reply .reply-wrapper .list .item .item-bd {
margin-left: 60px;
}
.reply .reply-wrapper .list .item .item-bd .top {
margin-bottom: 10px;
}
.reply .reply-wrapper .list .item .item-bd .user {
color: #666;
}
</style>

点进去就可以看到项目哇~

vue-cnodejs的更多相关文章

  1. vue分页组件table-pagebar

    之前一直接触都是原始的前端模型,jquery+bootstrap,冗杂的dom操作,繁琐的更新绑定.接触vue后,对前端MVVM框架有了全新的认识.本文是基于webpack+vue构建,由于之前的工作 ...

  2. Vue开源项目库汇总

    最近做了一个Vue开源项目库汇总,里面集合了OpenDigg 上的优质的Vue开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个star. UI组件 elem ...

  3. Vue 2.0初学后个人总结及分享

    摘要:最近在上海找工作,发现Vue前景还不错,于是就打算先学习一下(之前了解过,但是一直没提到日程上)这篇随笔当是为了自己学习之后,做一个小的阶段性总结.希望本文的内容对于刚开始接触vue的朋友们有点 ...

  4. vue.js应用开发笔记

    看vue.js有几天了,之前也零零散散的瞅过,不过一直没有动手去写过demo,这几天后台事比较少,一直在讨论各种需求(其实公司对需求还是比较重视与严谨的,一个项目需求讨论就差不多一周了,这要搁之前,天 ...

  5. Vue常用经典开源项目汇总参考-海量

    Vue常用经典开源项目汇总参考-海量 Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的 ...

  6. 基于angular的route实现单页面cnodejs

    Angular ui-router 前言 之前不太理解前端怎么实现路由功能,以前知道有一种方式使用html5的pushState可以操作url才实现路由的功能,在实践项目中也用过一次,后来这种操作叫成 ...

  7. 使用Vue快速开发单页应用

    本文所涉及代码全在vue-cnode 单页应用,即在一个页面集成系统中所有功能,整个应用只有一个页面.因为路由的控制在前端,单页面应用在页面切换时比传统页面更快,从而在前端体验更好. 将逻辑从后端转移 ...

  8. Vue.js学习网址

    Vue官网:http://cn.vuejs.org/v2/guide/index.html 淘宝镜像:http://npm.taobao.org/ Vue-router:https://router. ...

  9. Vue常用开源项目汇总

    前言:Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还 ...

  10. vue报错 Do not use built-in or reserved HTML elements as component id:header

    组件,不能和html标签重复 header组件,h5新标签重复 Do not use built-in or reserved HTML elements as component id:header ...

随机推荐

  1. java后台使用HttpURLConnection实现百度主动推送

    优点是快 不需要页面执行,,发布文章之后立即推送,所以,不管有没有人访问,都可以自动实时推送 尝试了一下httpclient,没找到相关资料,post方式无法塞url进去 最后改为 import ja ...

  2. java mybatis 参数问题

  3. BZOJ2120&&2453 数颜色&&维护队列

    2453: 维护队列 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1442 Solved: 678 [Submit][Status][Discuss ...

  4. UOJ#80. 二分图最大权匹配 模板

    #80. 二分图最大权匹配 描述 提交 自定义测试 从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生.编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr. 有若干个这 ...

  5. MySQL系列(十)--用户权限及远程访问

    本文基于MySQL8.0,记录一下完整的远程访问的过程,以及这个过程中可能遇到的问题,MySQL运行在阿里云服务器,操作系统:CentOS 7.6 64位 顺便说下,买服务器还是要双十二这种拉新活动再 ...

  6. php5 常量

    <?php define("GREETING", "Welcome to w3cschool.cn!", true); echo greeting; ?& ...

  7. CodeChef August Lunchtime 2014 题解

    A题 给一个由a和b两种类型的字符组成的字符串,每次可以从中选取任意长度的回文子序列(不一定连续)并删除.问最少需要几次能将整个字符串为空. 思路:如果本身是个回文串,那么只需要一次,否则需要两次(第 ...

  8. AutoMapper introduction

    http://automapper.org/ A convention-based object-object mapper映射. 100% organic and gluten-free. Take ...

  9. Windows下Git的下载、安装、设置用户名和邮箱、创建版本库等

    Git官网:https://git-scm.com/ 一.Git下载 官网首页下载,当前最新版本:2.24.1 本人下载的是Git for Windows版本:Git-2.24.1.2-64-bit. ...

  10. [Git高级教程(二)] 远程仓库版本回退方法 - 梧桐那时雨 - CSDN博客

    1 简介 最近在使用git时遇到了远程分支需要版本回滚的情况,于是做了一下研究,写下这篇博客. 2 问题 如果提交了一个错误的版本,怎么回退版本? 如果提交了一个错误的版本到远程分支,怎么回退远程分支 ...