用vue+webpack+es6+sass實現Cnode網站(一)

寫在文章前:最近把官網的vue文檔過了一遍,準備寫個項目來鞏固下本身對vue的學習。由於cnode網站有開放的api,因此我決定用vue+webpack+es6+sass的技術棧去實現這個網站(單頁面的形式)。這篇系列的文章我主要是分享下本身怎麼開發還有怎麼實現一個個vue組件去構建整個網站。關於webpack配合vue的使用能夠關注個人另一篇博文webpack+vue配置,感謝Cnode網站提供的開放API。javascript

建議閱讀前準備內容

1. 構建咱們的項目目錄

├── README.md          
├── index.html         // 項目入口文件
├── package.json       // 項目配置文件
├── src                // 生產目錄
│   ├── vue            // 組件
│   |    ├──about.vue
│   |    ├──artlist.vue
│   |    ├──article.vue
│   |    ├──login.vue
│   |    ├──loading.vue
│   |    ├──search.vue
│   ├── components     // 各類子組件
│   |    ├──header.vue
│   |    ├──returnTop.vue
│   |    ├──menu.vue
│   ├── js             // 外部引入的js文件
│   ├── scss           //scss文件
│   ├── img           //圖片文件
│   ├── filters.js     //過濾器
│   └── main.js        // Webpack 預編譯入口    
└── webpack.js          // Webpack 配置文件

2.今天要實現的一個效果

圖片描述

在上面的gif動畫中咱們總共看到了幾個頁面java

  • loading.vue(首頁過渡加載)node

  • artlist.vue(列表展現頁)
    幾個組件webpack

  • header.vue(頭部)css3

  • meun.vue(菜單欄)git

  • returnTop.vue(返回頂部)es6

在正式內容開始前先簡單的說下,咱們看到的一個頁面是由各個組件組成的,而咱們能夠把頁面拆分紅一個各個組件,每一個組件單獨一個文件,組件的結構是這樣的,避免內容過多下面講到的組件我都不寫style,具體代碼開源在了 github上,有興趣的能夠去看下。

<template>
    <!--html結構-->
</template>
<script>
    //js
</script>
<style>
    //style
</style>

3.具體頁面開發

3.1首頁過分也難loading.vue

咱們要實現的是一個loading圖等待2秒進入artlist列表頁

<template>
     <div>
          <img class="loading" src="../img/loading.gif" alt="">
     </div>
</template>
<script>
     export default {
          ready : function() {
               setTimeout(() => {
                    this.$route.router.go({name : 'artlist'});
               }, 2000);
          }
     }
</script>

3.1主題列表頁artlist.vue

咱們的列表頁的結構是這樣的:

<template>
     <nv-header></nv-header>
     <div class="artlist">
          <ul class="artlistTab clearfix">
               <li v-for="item in itemTab" :class="{'on':initIndex === $index}" v-on:click="changeTab($index)">{{item.title}}</li>
          </ul>
          <div class="artlistCon">
               <div v-for="art in artlist" class="artitem clearfix" v-link="{name:'article',params:{id:art.id}}">
                    <a class="avatar" href="javascript:void(0);">
                         <img :src="art.author.avatar_url" :alt="art.author.loginname">
                    </a>
                    <div class="art-inf">
                         <p class="title">{{art.title}}</p>
                         <span>{{art.reply_count}}/{{art.visit_count}}</span>
                         <span>{{art.create_at | getDateTime }}</span>
                    </div>
               </div>
          </div>
     </div>
     <nv-top></nv-top>
</template>

tab主題導航的渲染
咱們把列表的導航加載進來,官方API的有主體分類ask,share,job,good
因此得出咱們的數據itemTab。

itemTab : [
      {'title' : '所有', 'type' : 'all'},
      {'title' : '精華', 'type' : 'good'},
      {'title' : '分享', 'type' : 'share'},
      {'title' : '問答', 'type' : 'ask'},
      {'title' : '招聘', 'type' : 'job'}
]

而後在定義一個輸出請求接口的對象:

searchKey : {
     page : 1,
     limit : 20, //每頁加載20條
     tab : 'all' //主題 有all ask share job good
}

順便再定義哥artilist[]空數組來存放等下取出來的數據。

咱們要先定義拉取數據的方法函數,咱們把拉取到的數據列表放在咱們先前定義的artlist[]數組裏面,利用vue的雙向綁定的特性配合v-for咱們就能夠把咱們的列表頁的主題內容渲染出來了。

//獲取數據方法
gerArtlist : function() {
    let rqdata = $.param(this.searchKey);
    $.get('https://cnodejs.org/api/v1/topics?' + rqdata, (data) => {
         if(data.success){
              this.artlist = data['data'];
              this.scroll = true;
         }
    })

}
頁面剛打開的時候咱們要去取第一次的數據

ready : function() {
   this.gerArtlist(this.initIndex);
 });

切換主題的時候咱們要給每一個item綁定一個事件changeTab($index),利用$index這個索引,改變咱們this.searchKey.tab在去請求數據

// 標籤tab切換方法
changeTab : function(index) {
    this.initIndex = index;
    this.searchKey.tab = this.itemTab[index].type;
    this.artlist = [];
    this.searchKey.limit = 20;
    this.gerArtlist(this.initIndex);
}

咱們設置的是當前頁面打開的時候加載了20條數據,如今咱們要實現下拉,超過了必定的區域在去請求下一個20條的內容,就是改變searchKey.limit,每次觸發下拉條件就疊加20.

// 超過滾動獲取數據方法
scrollArtlist : function() {
    if(this.scroll){
         let totalheight = parseFloat($(window).height()) + parseFloat($(window).scrollTop());
         if ($(document).height() <= totalheight + 200) {
             this.scroll = false;
             this.searchKey.limit += 20;
             this.gerArtlist();
         }
    }
}

在ready裏面綁定下scroll

ready : function() {
       $(window).on('scroll',() => {
        this.scrollArtlist();
 });

3.2返回頂部組件
在咱們的列表頁引入返回頂部組件和頭部組件做爲子組件

components : {
    'nv-header' : require('../components/header.vue'),
    'nv-top' : require('../components/returnTop.vue')
}

返回頂部組件returnTop.vue

<template>
    <div class="return-top" v-show="showTop" v-on:click="returnTop"></div>
</template>
<script>
    export default {
        data : function() {
            return {
                showTop : false
            }
        },
        ready : function() {
            $(window).on('scroll', () => {
                if($(window).scrollTop() > 150){
                    this.showTop = true;
                }else{
                    this.showTop = false;
                }    
            })
        },
        methods : {
            returnTop : function() {
                $(window).scrollTop(0);
                this.showTop = false;
            }
        }
    }
</script>

3.3頭部組件

<template>
    <!-- 遮罩層 -->
    <div class="page-cover"  v-show="coverShow" v-on:click="hideMenu"></div>
    <!-- 頭部 -->
    <div class="header">
        <span class="left-menu" v-on:click="showMenu"></span>cnode.js
    </div>
    <nv-menu :showm="menuShow"></nv-menu>
</template>
<script>
    export default {
        data : function() {
            return {
                coverShow : false,
                menuShow : false
            }
        },
        methods : {
            showMenu : function() {
                this.coverShow = true;
                this.menuShow = true;
            },
            hideMenu : function() {
                this.coverShow = false;
                this.menuShow = false;
            }
        },
        components : {
            'nv-menu' : require('./menu.vue')
        }
    }
</script>

在咱們的header組件中咱們引入了一個menu組件,props : ['showm']利用父子組件間的通訊,給meun綁定了個:class="{'showMeun':showm}"利用css3來實現過渡

<template>
    <div class="meun" :class="{'showMeun':showm}">
        <ul>
            <li v-link="{name:'home'}">首頁</li>
            <li v-link="{name : 'search'}">搜索</li>
            <li v-link="{name : 'login'}">登陸</li>
            <li v-link="{name : 'login'}">註冊</li>
            <li v-link="{name : 'about'}">關於</li>
        </ul>
    </div>
</template>
<script>
    export default {
        props : ['showm']
    }
</script>
<style lang="sass">
    .meun {
        position: fixed;
        top: 0px;
        left:-200px;
        width: 200px;
        height: 100%;
        background: #444444;
        transition: all .3s ease;
        z-index: 99;
        ul {
            padding-top: 3rem;
            li {
                color: #fff;
                padding: 16px 0;
                text-align: left;
                text-indent: 10px;
                line-height: 20px;
                font-size: 20px;
                margin: 0 25px;
            }
        }
    }
    .showMeun {
        transform: translateX(200px);
    }
</style>

結束語

因爲是空閒的時間作的,因此只實現了部分功能,後面會繼續完善,源碼已經放在github

相關文章
相關標籤/搜索