基於Vue,Vue-router,Vuex的簡書網站模仿(二)

接着上一篇咱們接着講,關於這個網站的專題頁面和2015精選頁面,若是有小夥伴沒看過上一篇文章,這裏附上上一篇文章的的連接基於Vue,Vue-router,Vuex的簡書網站模仿
這裏是網站的源碼下載地址 Github Repo
這裏是Demo地址,在線感覺vue的魅力vue

頁面結構分析

圖片描述

  • App.vue:黃色框部分和紫色框部分git

  • Topic.vue:橙色框部分github

  • Topic_article.vue:藍色框部分(同時也是重點部分,實現點擊排序)vuex

學會分析頁面結構,是用vue開發一個比較重要的地方(我猜的),因此我再次分析了一次。頁面結構分析結束後,接下來就是上代碼的時候了。segmentfault

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>&nbsp;&nbsp;新建專題</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的代碼: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'}">最新更新&nbsp;&nbsp;·</a>            
            <a @click="change = 'hot'"
            :class="{active: change === 'hot'}">熱門排序&nbsp;&nbsp;·</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>
                        &nbsp;&nbsp;·&nbsp;&nbsp;{{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">&nbsp;&nbsp;簡書2015</span>
            <i>&nbsp;·&nbsp;</i>
            <span>每個月一篇好文章&nbsp;&nbsp;</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可好玩了,是的話那就對了,加油吧!騷年!結尾仍是那句話,求個收藏什麼的,若有錯誤,歡迎斧正。

相關文章
相關標籤/搜索