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

//根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. php7开启强类型模式

    版权声明: https://blog.csdn.net/shi_yi_fei/article/details/52006809 我们知道php是一种弱类型的编程语言,但是php7已经有所改变,可以支持 ...

  2. 分享一个百度大牛的Python视频系列下载

    好像是百度资深大数据工程师 在录制Python视频课程讲课,包括Python基础入门.数据分析.网络爬虫.大数据处理.机器学习.推荐系统等系列,他还在不停地录制,课程感觉很不错,视频网盘分享给大家 学 ...

  3. VS中warning MSB8004和error MSB4018解决方案

    问题如下: warning MSB8004: Output Directory does not end with a trailing slash.  This build instance wil ...

  4. mybatis学习:mybatis的环境搭建与入门

    一.mybatis的概述: mybatis是一个持久层框架,用java编写 它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接登繁杂过程 它使用了ORM思想 ...

  5. JS---案例:滚动条

    案例:滚动条 html框架分为4部分,最外面的div, 放文字的div, 装滚动条的div层,以及滚动条本身放在一个div里面 <!DOCTYPE html> <html> & ...

  6. 2018-8-10-如何使用-C#-爬虫获得专栏博客更新排行

    title author date CreateTime categories 如何使用 C# 爬虫获得专栏博客更新排行 lindexi 2018-08-10 19:16:51 +0800 2018- ...

  7. 洛谷P1970 [NOIP2013提高组Day2T2] 花匠

    P1970 花匠 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定 把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希 望剩下的花排 ...

  8. 有趣的HTML5 Web SQL 数据库

    Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs. 核心方法 以下是规范中定义的三个核心方法: openD ...

  9. 转:解决Onethink上传视频的问题 超棒的解决方案

    用过Onethink的都知道,它是不能上传视频的. 有人想到用上传附件的方式上传视频,但是结果……就是提示没有上传文件. 要是正常上传个一两兆的图片啊,压缩文件什么的还是可以的. 所以,重点来了 怎么 ...

  10. Cron定时任务应用到Thinkphp – 贤生博客

    Cron定时任务应用到Thinkphp 安装crontab: yum install crontabs 关于cron的一些命令: /sbin/service crond start //启动服务 /s ...