接着上一篇我们接着讲,关于这个网站的专题页面和2015精选页面,如果有小伙伴没看过上一篇文章,这里附上上一篇文章的的链接基于Vue,Vue-router,Vuex的简书网站模仿
这里是网站的源码下载地址 Github Repo
这里是Demo地址,在线感受vue的魅力
页面结构分析
App.vue
:黄色框部分和紫色框部分Topic.vue
:橙色框部分Topic_article.vue
:蓝色框部分(同时也是重点部分,实现点击排序)
学会分析页面结构,是用vue开发一个比较重要的地方(我猜的),所以我再次分析了一次。页面结构分析结束后,接下来就是上代码的时候了。
Topic.vue(橙色框部分)
topic.vue
部分和上一篇文章的home.vue
部分是如出一辙的,为了让大家加深印象,我就再讲一次(我不会讲我是来凑字数的,嘿嘿)。上代码:
<template>
<div>
<div class="showbar">
<div class="cover-image_2"></div>
<div class="text" style="text-shadow:1px 1px 1px #000000">
<h1>专题</h1>
<h3>让思想汇聚,流传</h3>
<p style="font-size:14px;margin-bottom:5px">专题内容由多位写作者提供</p>
<a href="#"><i class="fa fa-pencil"></i> 新建专题</a>
</div>
</div>
<div class="article-page">
<nav>
<span class="search clearfloat">
<span class="input">
<input type="search" placeholder="搜索">
</span>
<span class="search-icon"><i class="fa fa-search"></i></span>
</span>
</nav>
<div class="article-list">
<ul class="btn-group">
<li :class="{active: show === 'hot'}">
<a @click="displayTopic('hot')"
v-link="'/topic/topic_article'"
>热门</a></li>
<li :class="{active: show === 'recommend'}">
<a @click="displayTopic('recommend')"
v-link="'/topic/topic_article'"
>推荐</a></li>
</div>
<router-view></router-view>
</div>
</div>
</template>
<script>
import {displayTopic} from '../vuex/actions'
export default {
vuex:{
getters:{
show: state => state.show_2
},
actions:{
displayTopic
}
}
}
</script>
由于橙色框部分里热门和推荐两个导航按钮,要根据两个按钮展示不同的文章,这就和上一篇文章里的Home.vue里实现的方式一样,我们通过:class="{active: show === 'hot'}
来判断当前按钮是否处于被点击状态,这里的show来自于vuex(getters)获取到的show,并且给它加上不一样的样式。通过@click="displayTopic('hot')
点击事件来更换不同的show值和文章内容。这样我们就实现了点击切换按钮状态和文章区域内容。下面放上点击事件的代码:
actions.js:
export const displayTopic = ({ dispatch },show) => {
dispatch('DISPLAY_TOPIC',show)
}
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
topics:{
fir: {
img:'../../static/topic_1.jpg',
title:'游戏',
par:'玩转简书的第一步,从这个专题开始。\
想上首页热门榜么?好内容想被更多人看到么?来投稿吧!\
如果被拒也不要灰心哦~入选文章会进一个队列挨个上首页,请耐心等待。\
投稿必须原创。如果发现有非...',
number:'97233',
concern:'121.7',
keys:'故事、连载',
time:'20160620'
},
sec: {
img:'../../static/topic_3.jpg',
title:'诗',
par:'诗,让你感受自己的心灵。\
专题主编:苏锦年 投稿须知:\
1.本专题收录古诗、词、现代诗以及诗词点评及指导。\
2.内容必须为原创,切勿用其他诗人的诗句。\
3.文章排版整洁,注意...',
number:'35420',
concern:'146.6',
keys:'诗',
time:'20160630'
}
},
show_2:'hot'
}
const mutations = {
DISPLAY_TOPIC (state, show) {
const topic = {
hot: {
fir: {
img:'url../../static/vue-demo-hot.jpg',
title:'游戏',
par:'玩转简书的第一步,从这个专题开始。\
想上首页热门榜么?好内容想被更多人看到么?来投稿吧!\
如果被拒也不要灰心哦~入选文章会进一个队列挨个上首页,请耐心等待。\
投稿必须原创。如果发现有非...',
number:'97233',
concern:'121.7k',
keys:'故事、连载'
},
sec: {
img:'../../static/topic_3.jpg',
title:'诗',
par:'诗,让你感受自己的心灵。\
专题主编:苏锦年 投稿须知:\
1.本专题收录古诗、词、现代诗以及诗词点评及指导。\
2.内容必须为原创,切勿用其他诗人的诗句。\
3.文章排版整洁,注意...',
number:'35420',
concern:'146.6k',
keys:'诗',
time:'20160630'
}
},
recommend: {
fir: {
img:'../../static/topic_1.jpg',
title:'游戏',
par:'玩转简书的第一步,从这个专题开始。\
想上首页热门榜么?好内容想被更多人看到么?来投稿吧!\
如果被拒也不要灰心哦~入选文章会进一个队列挨个上首页,请耐心等待。\
投稿必须原创。如果发现有非...',
number:'97233',
concern:'121.7',
keys:'故事、连载',
time:'20160620'
},
sec: {
img:'../../static/topic_3.jpg',
title:'诗',
par:'诗,让你感受自己的心灵。\
专题主编:苏锦年 投稿须知:\
1.本专题收录古诗、词、现代诗以及诗词点评及指导。\
2.内容必须为原创,切勿用其他诗人的诗句。\
3.文章排版整洁,注意...',
number:'35420',
concern:'146.6',
keys:'诗',
time:'20160630'
},
thi: {
img:'../../static/topic_2.jpg',
title:'@IT互联网',
par:'@IT 专题 由 IT大分类,转定位于IT·互联网行业观察与思考,数码产品极客体验。\
主编:向右奔跑 http://www.jianshu.com/users/54b5900965ea...',
number:'8409',
concern:'111.1',
keys:'互联网、产品、科技',
time:'20160625'
}
}
}
state.show_2 = show
state.topics = topic[show]
}
}
export default new Vuex.Store({
state,
mutations
})
这里面我省掉了上一章的代码。这里面我才用模拟的数据,可以清楚的看到实现方式。接下来讲解排序部分,这里算是一个重点吧,因为我在这里遇到了坑。
Topic_article.vue(蓝色框部分)
这部分我们要实现根据小导航的切换来显示不同的顺序(热门,推荐,最新更新),这里我只做了推荐和最新更新这两部分。首先要实现这种效果,我们第一时间想到的就应该是和大导航一样给小导航添加class绑定和点击事件。接下来看代码,先是Topic_article.vue的代码:
<template>
<div class="topic_article_container">
<div class="sequence-nav" v-if="show === 'recommend'">
<a @click="sortContent('time'), change = 'new'"
:class="{active: change === 'new'}">最新更新 ·</a>
<a @click="change = 'hot'"
:class="{active: change === 'hot'}">热门排序 ·</a>
<a @click="sortContent('concern'), change = 'new'"
:class="{active: change === 'concern'}">关注度排序</a>
</div>
<ul>
<li v-for="content in topic">
<a href="" class="topic_article_img"><img :src="content.img"></a>
<div class="topic_content">
<h5>{{ content.title }}</h5>
<p>{{ content.par }}</p>
<div class="topic_button">
<a href="#"><i class="fa fa-fw fa-plus"></i><span>添加关注</span></a>
</div>
<p>
<a href="#" style="color:#4094c7">{{ content.number}}篇文章</a>
· {{content.concern}}k人关注
<span class="topic_tag"><i class="fa fa-tags"></i>{{ content.keys}}</span>
</p>
</div>
</li>
</ul>
</div>
</template>
<script>
import { sortContent } from '../vuex/actions'
export default {
data (){
let change = 'hot'
return {change}
},
vuex: {
getters: {
topic: state => state.topics,
show: state => state.show_2
},
actions: {
sortContent
}
}
}
</script>
因为这个小导航栏在热门页面里是没有的,这里才用了vue的v-if功能实现,通过getters获得此时的show变量,判断是否是推荐页面,如果是就显示。这里的文章依然采用vue的列表渲染功能(真好用),同时给小导航栏设置了点击事件,和改变背景的一个变量。接下来放上actions.js里面的代码:
export const sortContent = ({ dispatch },method) => {
dispatch('SORTCONTENT',method)
}
也是那么短小精悍,毕竟我只用于分发事件。下面是store.js里面的代码:
SORTCONTENT (state, method){
const temp = state.topics
let arr = []
let Arr = objClone(state.topics)
switch(method){
case 'time':
arr = [temp.fir.time, temp.sec.time, temp.thi.time].sort()
break
case 'concern':
arr = [temp.fir.concern, temp.sec.concern, temp.thi.concern].sort()
break
default:
break
}
for(let keys in state.topics){
if(Arr[keys][method] == arr[2]){
state.topics.fir = Arr[keys]
}
else if(Arr[keys][method] == arr[1]){
state.topics.sec = Arr[keys]
}
else if(Arr[keys][method] == arr[0]){
state.topics.thi = Arr[keys]
}
}
function objClone(myObj){
if(typeof(myObj) != 'object') return myObj;
if(myObj == null) return myObj;
var myNewObj = new Object();
for(var i in myObj){
myNewObj[i] = objClone(myObj[i]);
}
return myNewObj;
}
}
这个事件的代码也很好理解,通过对不同的method,把不同的变量进行排序后赋值给一个数组,然后依次与topics做匹配,因为我这里只模拟了三个数据,故这部分操作比较简单。重点的是当我匹配topics里第三个属性(thi)的值的时候,这个时候topics里的第三个属性值已经变了(因为如果第二个属性(sec)的值是最小的,就会把这个属性赋给第三个属性,这时候第三个属性就变了,所以第三次匹配的时候还是得出和第二次同样的结果)。这时候我的做法是克隆一个和topics相同的对象,用这个对象去匹配,匹配好了之后把这个对象里相应的值赋值给topics。我讲的有点啰嗦,具体看代码实现。(ps:克隆对象的时候,我竟然直接进行赋值克隆,殊不知都是指向同一个地址空间,后来了解到需要重新开一个地址空间才能克隆,故有了上面那段objClone函数。)
到这里简书两个主要的部分就讲完了(Home.vue,Topic.vue)
接下来说一说2015年精选页面
2015精选页面
这个页面相对来说比较简单,就一个vue的列表渲染(不用列表渲染的话代码太多,太长,关键是逼格不高),先上页面:
图中类似的标签有12个,故才用列表渲染来简化重复的代码,接下来是代码部分:
Bonus.vue
<template>
<div class="bonus-container">
<div class="bonus-header">
<span class="yellow"> 简书2015</span>
<i> · </i>
<span>每月一篇好文章 </span>
</div>
<div class="share">
<span><a href="#"><i class="fa fa-mobile"></i>手机查看效果更佳</a></span>
<span><a href="#"><i class="fa fa-weibo"></i>分享到微博</a></span>
<span><a href="#"><i class="fa fa-wechat"></i>分享到微信</a></span>
<span><a href="#">更多分享</a></span>
</div>
<ul class="text-list">
<li v-for="article in articles"
:style="{ background: article.article.bg, backgroundSize: '100%', backgroundRepeat: 'no-repeat', backgroundColor: '#ffffff'}"
<div class="content">
<a class="mask" href="#">
<div class="button">阅读全文></div>
</a>
<div class="bonus-text">
<div class="bonus-text-title">{{ article.article.title}}</div>
<div class="line"></div>
<div class="bonus-text-content">
{{article.article.content_1}}<br>
{{article.article.content_2}}<br>
{{article.article.content_3}}<br>
{{article.article.content_4}}<br>
{{article.article.content_5}}<br>
{{article.article.content_6}}<br>
</div>
</div>
<div class="author"></div>
</div>
</li>
</template>
<script>
export default {
data () {
let articles = ''
return {articles}
},
vuex: {
getters: {
texts: state => state.texts
}
},
ready: function() {
this.articles = [{article: this.texts.Jan}, {article: this.texts.Feb}, {article: this.texts.Mar},
{article: this.texts.Apr}, {article: this.texts.May}, {article: this.texts.Jun},
{article: this.texts.Jul}, {article: this.texts.Aug}, {article: this.texts.Sep},
{article: this.texts.Oct}, {article: this.texts.Nov}, {article: this.texts.Dec}]
}
}
</script>
store.js_Bonus部分
下面是store.js里面模拟的数据
texts:{
Jan:{
title:'给你90天,成为不一样的自己',
content_1:"如果你应付不了现在的生活和工作",
content_2:"无论你走到哪里,",
content_3:"无论你换了什么工作,什么公司,",
content_4:"都无济于事。",
content_5:"因为你根本没想让自己成熟起来,",
content_6:"想让变的更优秀也不过是一句口头禅。",
author:'',
bg:'url(../../static/bonus_1.jpg)'
},
Feb:{
title:'使你更有思想的20本书',
content_1:"真正伟大的当代文学,",
content_2:"正如人们借由狄更斯来了解十九世纪的英国,",
content_3:"后人也可以通过《自由》来了解",
content_4:"二十一世纪初期的美国。",
content_5:"",
content_6:"",
author:'',
bg:'url(../../static/bonus_2.jpg)'
},
Mar:{
title:'无感是最舒适的爱情',
content_1:"爱情原本就是个很娇气的东西,",
content_2:"它经不起太多的矫情,你死我活和无理取闹,",
content_3:"也经不起任何的伪装,刻意讨好和忍辱负重。",
content_4:"当她拂去所有的惊喜,荣幸,不敢置信和小心翼翼,",
content_5:"才是爱情最原本的样子。",
content_6:"当她不再刻意的感受他的存在,",
author:'',
bg:'url(../../static/bonus_3.jpg)'
},
Apr:{
title:'无感是最舒适的爱情',
content_1:"爱情原本就是个很娇气的东西,",
content_2:"它经不起太多的矫情,你死我活和无理取闹,",
content_3:"也经不起任何的伪装,刻意讨好和忍辱负重。",
content_4:"当她拂去所有的惊喜,荣幸,不敢置信和小心翼翼,",
content_5:"才是爱情最原本的样子。",
content_6:"当她不再刻意的感受他的存在,",
author:'',
bg:'url(../../static/bonus_4.jpg)'
}
这里我只给出5条数据,后面都是重复的,代码就不过多讲解了,实现方式和前面的一样。看到这里是不是感觉写一个网页很简单,是不是觉得Vue可好玩了,是的话那就对了,加油吧!骚年!
结尾还是那句话,求个收藏什么的,如有错误,欢迎斧正。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。