接着上一篇咱们接着讲,关于这个网站的专题页面和2015精选页面,若是有小伙伴没看过上一篇文章,这里附上上一篇文章的的连接基于Vue,Vue-router,Vuex的简书网站模仿
这里是网站的源码下载地址 Github Repo
这里是Demo地址,在线感觉vue的魅力vue
App.vue
:黄色框部分和紫色框部分git
Topic.vue
:橙色框部分github
Topic_article.vue
:蓝色框部分(同时也是重点部分,实现点击排序)vuex
学会分析页面结构,是用vue开发一个比较重要的地方(我猜的),因此我再次分析了一次。页面结构分析结束后,接下来就是上代码的时候了。segmentfault
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 })
这里面我省掉了上一章的代码。这里面我才用模拟的数据,能够清楚的看到实现方式。接下来说解排序部分,这里算是一个重点吧,由于我在这里遇到了坑。网站
这部分咱们要实现根据小导航的切换来显示不一样的顺序(热门,推荐,最新更新),这里我只作了推荐和最新更新这两部分。首先要实现这种效果,咱们第一时间想到的就应该是和大导航同样给小导航添加class绑定和点击事件。接下来看代码,先是Topic_article.vue的代码:this
<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年精选页面
这个页面相对来讲比较简单,就一个vue的列表渲染(不用列表渲染的话代码太多,太长,关键是逼格不高),先上页面:
图中相似的标签有12个,故才用列表渲染来简化重复的代码,接下来是代码部分:
<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里面模拟的数据
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可好玩了,是的话那就对了,加油吧!骚年!结尾仍是那句话,求个收藏什么的,若有错误,欢迎斧正。