1.cnode社区的基本构架
组件:
Header 头部
PostList 列表
Article 文章的详情页
SlideBar 侧边栏
UserInfo 用户个人信息
Pagination 分页组件
2.从零开始的实战
初始化项目
vue init webpack cnode
cnpm install
npm run dev
3. Header组件
引入组件
import Header from "./components/Header";
export default {
name: "App",
components: {
Header
}
};
在App.vue中插入组件
<Header></Header>
4. ProstList
API接口:https://cnodejs.org/api/v1/topics 获取帖子列表
拿到的参数分析
头像:author.avatar_url
回复量/浏览量 :reply_count/visit_count
帖子的标题:title
需要使用到过滤器:
时间:last_reply_at
帖子分类:top: 代表是否置顶
good: 代表是否精华
tab 是表示除了置顶和精华之外的其余分区
share 分享
ask 问答
job 招聘
引入Axios
npm install anxious
在main.js中引入Axios
import Axios from 'axios'
Vue.prototype.$http = Axios;
利用一个v-for循环来把参数放到dom节点上
<li v-for="post in posts">
<!--头像-->
<img :src="post.author.avatar_url" />
<!--回复/浏览-->
<span>
<span class="reply_count">{{post.reply_count}}</span>
/{{post.visit_count}}
</span>
<span
:class="[{put_good:(post.good == true),put_top:(post.top == true),
'topiclist-tab':(post.good != true && post.top !=true)}]"
>
<span>{{post| tabFormatter}}</span>
</span>
<!--标题-->
<span>{{post.title}}</span>
<!--时间-->
<span class="last_reply">{{post.last_reply_at | formatDate}}</span>
</li>
在main.js中添加过滤器,处理时间
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 / 6000 < 60)) {
return parseInt((time / 6000)) + '分钟前'
} 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)) + '年前'
}
})
在main.js中添加过滤器处理小标题
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 '招聘'
}
})
5. Article
API https://cnodejs.org/api/v1/topic/ + 帖子ID
写入header
<div class="topic_header">
<div class="topic_title">{{post.title}}</div>
<ul>
<li>·发布于: {{post.create_at |formatDate}}</li>
<li>• 作者:{{post.author.loginname}}</li>
<li>· {{post.visit_count}}次浏览</li>
<li>· 来自{{post | tabFormatter}}</li>
</ul>
<div v-html="post.content" class="topic_content"></div>
</div>
写入回复板块
<div>
<div class="topbar">回复</div>
<div v-for="(reply,index) in post.replies" class="replySec">
<div class="replyUp">
<router-link>
<img src="reply.author.avatar_url" />
</router-link>
<router-link>
<span>{{reply.author.loginname}}</span>
</router-link>
<span>☝{{index + 1}}楼</span>
<span v-if="reply.ups.length>0">{{reply.ups.length}}</span>
</div>
<p v-html="reply.content"></p>
</div>
</div>
methods
利用axious调入api地址
methods: {
getArticleData() {
this.$http
.get("https://cnodejs.org/api/v1/topic/" + this.$route.params.id)
.then(res => {
if (res.data.success == true) {
this.post = res.data.data;
this.isLoading = false;
}
})
.catch(function(err) {
console.log(err);
});
}
},
在postlist上加入router-link
加入路由跳转
<router-link
:to="{
name: 'post_content',
params: {
id: post.id
}
}"
>
<span>{{post.title}}</span>
</router-link>
在index.js加入router路由跳转
export default new Router({
routes: [{
name: 'root',
path: '/',
components: {
main: PostList
}
},
{
name: 'post_content',
path: '/topic/:id',
components: {
main: Article
}
}]
4.UserInfo
https://cnodejs.org/api/v1/user/
在article板块中加入router-link
<router-link
:to="{
name:'user_info',
params: {
name: reply.author.loginname
}
}"
>
<img :src="reply.author.avatar_url" alt />
</router-link>
在index.js中添加路由
{
name: 'user_info',
path: '/userinfo/:name',
components: {
main: UserInfo
}
},
在回复板块上路由重新跳转回Postlist板块
<div class="replies">
<p>回复的主题</p>
<ul>
<li v-for="item in userinfo.recent_replies" :key="item">
<router-link
:to="{
name: 'post_content',
params: {
id: item.id
}
}"
>{{item.title}}</router-link>
</li>
</ul>
</div>
在创建主题板块上也是同理
div class="topics">
<p>创建的主题</p>
<ul>
<li v-for="item in userinfo.recent_topics" :key="item">
<router-link
:to="{
name: 'post_content',
params: {
id: item.id
}
}"
>{{item.title}}</router-link>
</li>
</ul>
</div>
</div>
SlideBar注意事项
1.需要在PostList上多加上一个参数来显示作者名
<router-link
:to="{
name: 'post_content',
params: {
id: post.id,
name: post.author.loginname
}
}"
>
<span>{{post.title}}</span>
</router-link>
同理修改路由跳转
{
name: 'post_content',
path: '/topic/:id&author=:name',
components: {
main: Article,
slidebar: SlideBar
}
},
2.处理回复的消息需要得到最近的五条,此时需要利用computed属性
<li v-for="list in topiclimitby5" :key="list">
<router-link
:to="{
name: 'post_content',
params: {
id: list.id,
name: list.author.loginname
}
}"
>{{list.title}}</router-link>
</li>
computed: {
topiclimitby5() {
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);
}
}
},
3.由于点击连接主题路由跳转的地址相同,需要在Article组件中加入watch观察路由跳转
watch: {
$route(to, from) {
this.getArticleData();
}
}
6.Pagination注意事项
1.注意如何进行删除button和添加button
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);
}
2.如何处理首页和下一页上一页的数据
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;
}
3.在Poslist中获得Pagination的参数
1.在组件添加方法
<pagination @handleList="renderList"></pagination>
2.方法
renderList(value) {
this.postpage = value;
this.getData();
}
3.在pagination中传递数据
this.$emit("handleList", this.currentPage);