接着上一篇我们接着讲,关于这个网站的专题页面和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 = showstate.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.topicslet arr = []let Arr = objClone(state.topics)switch(method){case 'time':arr = [temp.fir.time, temp.sec.time, temp.thi.time].sort()breakcase 'concern':arr = [temp.fir.concern, temp.sec.concern, temp.thi.concern].sort()breakdefault: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可好玩了,是的话那就对了,加油吧!骚年!
结尾还是那句话,求个收藏什么的,如有错误,欢迎斧正。